1

I have a shared library written in C++ that i need to expose for C as well.

Let's say i have to wrap the following class :

class Foo
{
public:
    const std::vector<int> &getList() const
    {
        return m_list;
    }
private:
    std::vector<int> m_list {0, 1, 2, 3, 4};           
};

First wrapper version :

struct wrap_foo
{
    Foo m_f;
};

typedef struct wrap_foo *wrap_foo_t;

const int *getList(wrap_foo_t f) // useful ?
{
    return f->m_f.getList().data();
}

int listSize(wrap_foo_t f)
{
    return f->m_f.getList().size();
}

int getVal(wrap_foo_t f, int i)
{
    return  f->m_f.getList().at(i);
}

wrap_foo_t createFoo()
{
    return new wrap_foo;
}

void cleanFoo(wrap_foo_t f)
{
    delete f;
}

2nd wrapper version :

struct vec
{
    const int *first;
    int size; // number of elements
};
    
typedef struct vec *vec_t;

vec_t getList2(wrap_foo_t f)
{
    vec_t v = new vec;
    v->first = f->m_f.getList().data();
    v->size = f->m_f.getList().size();
    return v;
}

int getVal2(vec_t v, int i)
{
    return *(v->first + i);
}
   
void cleanVec(vec_t v)
{
    delete v;
}

For the first version, the C client code would then use the C API in this way :

wrap_foo_t wf = createFoo();

for (int i = 0; i < listSize(wf); i++)
    printf("v = %d\n", getVal(wf, i));

cleanFoo(wf);

And in the 2nd version :

wrap_foo_t wf2 = createFoo();
vec_t list = getList2(wf2);

for (int i = 0; i < list->size; i++)
    printf("v = %d\n", getVal2(list, i));

cleanVec(list);
cleanFoo(wf2);

The internal list is wrapped into a c structure in the second version, keeping its size. In the first version, each time the class is extended (for example by adding other getList methods, getList1, getList2,..), 2 wrappers functions are needed (one to return a pointer, one to return the size).

Is there a better choice to wrap this class ? (except from errors that are not handled in this small example here)

Thank you.

Fryz
  • 2,119
  • 2
  • 25
  • 45
  • 3
    I don't understand why you are duplicating the functions in your wrapper. Why not implement the logic directly in the free functions, e.g.: `int *getList(wrap_foo_t f) { return f->m_f.getList().data(); }`? The use of a `friend` class also seems to be unnecessary – UnholySheep Apr 15 '22 at 16:38
  • 1
    Also you can return more than one value from a function in C by using pointer arguments (or returning a custom `struct`) if you don't want to write 2 separate functions – UnholySheep Apr 15 '22 at 16:43
  • Related: https://stackoverflow.com/questions/1429440/c-class-or-struct-compatiblity-with-c-struct – John Bollinger Apr 15 '22 at 16:45
  • @UnholySheep Indeed, i have edited the question, friendship and duplicated functions are not needed here. – Fryz Apr 15 '22 at 17:00
  • i am not sure `const int *getList(wrap_foo_t f)` is actually necessary in the first version as well, as we access the list through the opaque type `wrap_foo_t` – Fryz Apr 15 '22 at 17:29

0 Answers0