I look at the packaging of some c libraries in C ++, and I'm not sure if the best way is to wrap opaque pointers.
When a C structure is part of a public API
typedef struct _SomeType { int a; int b; } SomeType_t;
If there are multiple member functions:
void SomeTypeFoo( SomeType_t* obj, ... ); void SomeTypeBar( SomeType_t* obj, ... );
I like the approach coming from the base to just associate these “members” as real members of the class. i.e:.
class SomeTypeWrapper: public SomeType_t { void foo( ... ); void bar( ... ); };
As I understand it, I believe SomeTypeWrapper is “binary compatible” with struct _SomeType , so SomeTypeWrapper* can be dropped before SomeType_t* , so the C ++ method implementation can be:
SomeTypeWrapper::foo( ... ) { SomeTypeFoo( (SomeType_t*)this, ... ); }
See note [1].
However, in some libraries, they prefer the structure definition to be private (I assume this is to allow changes to the implementation without changing the headers / APIs). So in the headers I have something like this:
typedef struct _SomeType SomeType_t;
And then all the member functions deal with these opaque pointers. To wrap these methods in an interface, what I have done so far is to provide a class containing a pointer.
class SomeTypeWrapper { private: SomeType_t* m_data; public: SomeTypeWrapper( SomeType_t* data ): m_data(data){} void foo(...); void bar(...); };
This means that for any c library function that returns such an opaque pointer, I must allocate a new object to carry this pointer. For many libraries, which are probably fine, but this project complicates the implementation of the shell and for high-speed c-libraries that deal with a large number of small objects, I suspect that this additional object overhead can lead to a significant decrease in performance. In addition, the base object can be considered a link, so in some cases I have to make decisions about whether SomeWrapperType increases the reference count, implements a copy constructor, has a private constructor, etc.
In most cases, I am happy to pay a fine for a better interface, but I am looking for other options. Is there a cleaner way to deal with opaque c-pointers in the C ++ wrapper library? Related: is there a good way to implement wrapper classes so that C ++ headers do not include c-library headers And do not require the placement of wrapper objects?
Note. [1]: I believe that this cast is safe as long as the same compiler is used, and SomeTypeWrapper does not add additional members and does not have virtual methods. In the same compiler, I assume that the c-library compiled by gcc will work with the C ++ shell compiled by the same gcc. Perhaps this is not guaranteed?