samedi 3 février 2018

Wrapping array of C objects into C++ class

I have C library with such API:

extern "C" {
    typedef struct Opaque Opaque;

    Opaque *foo_new();
    void foo_delete(Opaque *);
    int foo_f(Opaque *, int);
}

To simplify it's usage I wrap it in such way:

class Foo final {
public:
    Foo() { self_ = foo_new(); }
    ~Foo() { foo_delete(self_); }
    //code for copy/move constructor and operator=
    int f(int a) { return foo_f(self_, a); }
private:
    Opaque *self_;
};

All great, but then I have to wrap array of this opaque objects:

extern "C" {
    typedef struct OpaqueArray OpaqueArray;

    OpaqueArray *calc_foo_array();
    void foo_array_delete(OpaqueArray *);
    Opaque *foo_array_elem(OpaqueArray *, size_t i);
}

So I need implement class FooArray:

class FooArray final {
public:
    ??? operator[](const size_t i) {
       auto obj = foo_array_elem(self_, i);
       ???
    }
private:
    OpaqueArray *self_;
};

But what should I return as result of operator[]?

I can create Foo from Opaque *, but then Foo::~Foo() is free part of array, what is wrong. I can create FooRef that would be exactly the same as Foo, but do not call foo_delete, but actually I have several such C classes, and I prefer do not create so many code duplicates. May be I can somehow use reinterpret_cast, because of sizeof(Foo) = sizeof(Opaque *) and return Foo & from operator[], but Foo & actually is Opaque **, so I need somewhere hold Opaque to make it address stable.

May be there is some standard solution for such kind of problem?

Aucun commentaire:

Enregistrer un commentaire