Wrapping C++ Class API for C Consumption

Wrapping C++ class API for C consumption

Foreach public method you need a C function.

You also need an opaque pointer to represent your class in the C code.

It is simpler to just use a void* though you could build a struct that contains a void* and other information (For example if you wanted to support arrays?).

Fred.h
--------------------------------

#ifdef __cplusplus
class Fred
{
public:
Fred(int x,int y);
int doStuff(int p);
};
#endif

//
// C Interface.
typedef void* CFred;

//
// Need an explicit constructor and destructor.
extern "C" CFred newCFred(int x,int y);
extern "C" void delCFred(CFred);

//
// Each public method. Takes an opaque reference to the object
// that was returned from the above constructor plus the methods parameters.
extern "C" int doStuffCFred(CFred,int p);

The the implementation is trivial.

Convert the opaque pointer to a Fred and then call the method.

CFred.cpp
--------------------------------

// Functions implemented in a cpp file.
// But note that they were declared above as extern "C" this gives them
// C linkage and thus are available from a C lib.
CFred newCFred(int x,int y)
{
return reinterpret_cast<void*>(new Fred(x,y));
}

void delCFred(CFred fred)
{
delete reinterpret_cast<Fred*>(fred);
}

int doStuffCFred(CFred fred,int p)
{
return reinterpret_cast<Fred*>(fred)->doStuff(p);
}

Strategies to wrap C API for C++ consumption

What I have in mind is

template <typename H> using create_t = void (*)(H**, error_details_t*);
template <typename H> using destroy_t = void (*)(H*, error_details_t*);
template <typename H> using get_data_t = void (*)(H*, uint8_t* buffer, error_details_t*);

template <typename H,
create_t<H> create,
destroy_t<H> destroy,
get_data_t<H> get_data>
class backend
{
backend() { error_details_t err; create(&handle, err);}
~backend() { error_details_t err; destroy(handle, err);}

backend(const backend&) = delete;
backend& operator =(const backend&) = delete;
backend(backend&&) = delete;
backend& operator =(backend&&) = delete;

void get_data(uint8_t* buffer)
{
error_details_t err;
get_data(handle, buffer, &err);
}

private:
H* handle = nullptr;
};

using bull = backend<bull_handle_t, &bull_create, &bull_destroy, &bull_get_data>;
using frog = backend<frog_handle_t, &frog_create, &frog_destroy, &frog_get_data>;
using bullfrog = backend<bullfrog_handle_t,
&bullfrog_create,
&bullfrog_destroy,
&bull_get_data>;

Maybe error_details_t can be a member,
and you should also handle error.

Developing C wrapper API for Object-Oriented C++ code

This is not too hard to do by hand, but will depend on the size of your interface.
The cases where I've done it were to enable use of our C++ library from within pure C code, and thus SWIG was not much help. (Well maybe SWIG can be used to do this, but I'm no SWIG guru and it seemed non-trivial)

All we ended up doing was:

  1. Every object is passed about in C an opaque handle.
  2. Constructors and destructors are wrapped in pure functions
  3. Member functions are pure functions.
  4. Other builtins are mapped to C equivalents where possible.

So a class like this (C++ header)

class MyClass
{
public:
explicit MyClass( std::string & s );
~MyClass();
int doSomething( int j );
}

Would map to a C interface like this (C header):

struct HMyClass; // An opaque type that we'll use as a handle
typedef struct HMyClass HMyClass;
HMyClass * myStruct_create( const char * s );
void myStruct_destroy( HMyClass * v );
int myStruct_doSomething( HMyClass * v, int i );

The implementation of the interface would look like this (C++ source)

#include "MyClass.h"

extern "C"
{
HMyClass * myStruct_create( const char * s )
{
return reinterpret_cast<HMyClass*>( new MyClass( s ) );
}
void myStruct_destroy( HMyClass * v )
{
delete reinterpret_cast<MyClass*>(v);
}
int myStruct_doSomething( HMyClass * v, int i )
{
return reinterpret_cast<MyClass*>(v)->doSomething(i);
}
}

We derive our opaque handle from the original class to avoid needing any casting, and (This didn't seem to work with my current compiler). We have to make the handle a struct as C doesn't support classes.

So that gives us the basic C interface. If you want a more complete example showing one way that you can integrate exception handling, then you can try my code on github : https://gist.github.com/mikeando/5394166

The fun part is now ensuring that you get all the required C++ libraries linked into you larger library correctly. For gcc (or clang) that means just doing the final link stage using g++.

Wrapping old school C lib within C++ class (and a callback without user param)

For those who are interested, here is the way I solved my own problem:

I use a pool of extern C functions that take the place of the missing user param in my old school lib.

The main limitation of this approach is that the number of concurrency instances is limited to a static arbitrary number.

//---------------------------------------------------------------------
//-- the c++ wrapper API

class Lib
{
public:
struct Functor
{
virtual int func ( int x ) const = 0 ;
};

Lib ( const Functor & f , int i ) ;
~Lib () ;
int process ( int x ) ;

protected:
struct PirvateLib ;
PirvateLib * m ;
};

//---------------------------------------------------------------------
//-- wrapper usage

struct MyFunctor : Lib::Functor
{
int d ;
MyFunctor ( int d ) : d(d) {}
int func ( int x ) const
{
return x + d ;
}
};

#include <iostream>

int main ()
{
Lib l1( MyFunctor( 100 ),10 ) ;
Lib l2( MyFunctor( 200 ),20 ) ;
Lib l3( MyFunctor( 300 ),30 ) ;
for ( int i = 0 ; i < 5 ; i++ )
std::cout << " " << l1.process( i ) << " // " << l2.process( i ) << " // " << l3.process( i ) << std::endl ;
}

//---------------------------------------------------------------------
//-- code of the old school lib (I can't change it)

extern "C" {

typedef int (*func_t)(int) ; // callback without any "void * user_param"

typedef struct
{
func_t f ;
int i ;
} t_lib_struct ;

void lib_init ( t_lib_struct * self , func_t f , int i )
{
self->f = f ;
self->i = i ;
}

void lib_close ( t_lib_struct * self )
{
self->f = 0 ;
self->i = 0 ;
}

int lib_process ( t_lib_struct * self , int x )
{
return self->f( x + self->i ) ;
}
}

//---------------------------------------------------------------------
//-- the not-very-clean-solution: a global pool of functions that takes the place of the missing user-param

static const Lib::Functor * get ( int i ) ;

struct funcs_t
{
func_t func ;
const Lib::Functor * lib_functor ;
bool isfree ;
} ;

#define FOR_ALL(f) f(0)f(1)f(2)f(3)f(4)f(5)f(6)f(7)f(8)f(9)f(10)f(11)f(12)f(13)f(14)f(15) // if necessary, add f(16)f(17)...

// create a pool of 16 functions...
extern "C" {
#define FUNC_DEF(i) static int wrapped_func_##i ( int x ) { return get(i)->func(x) ;}
FOR_ALL(FUNC_DEF)
}

// ....and an associated array of structs (terminated by a "null" element)
#define FUNC_STRUCT(i) { wrapped_func_##i , 0 , true },
static funcs_t funcs [] = { FOR_ALL(FUNC_STRUCT) {0,0,false} } ;

static int alloc () // return the index of a free slot, or -1
{
for ( int i = 0 ; funcs[i].func ; i++ )
if (funcs[i].isfree)
return funcs[i].isfree = false || i ;
return -1 ; // allocation error not managed!
}

static void free ( int i )
{
funcs[i].isfree = true ;
}

static const Lib::Functor * get ( int i )
{
return funcs[i].lib_functor ;
}

//---------------------------------------------------------------------
//-- wrapper implementation

struct Lib::PirvateLib
{
t_lib_struct lib ;
int i ;
};

Lib::Lib ( const Functor & f , int i ) : m ( new Lib::PirvateLib )
{
m->i = alloc() ;
funcs[m->i].lib_functor = &f ;
lib_init( &m->lib,funcs[m->i].func,i ) ;
}

Lib::~Lib ()
{
lib_close( &m->lib ) ;
free( m->i ) ;
delete m ;
}

int Lib::process ( int x )
{
return lib_process( &m->lib,x ) ;
}

And the output:

110 // 320 // 330
111 // 321 // 331
112 // 322 // 332
113 // 323 // 333
114 // 324 // 334

How to convert exceptions to errors and error messages when wrapping C++ classes API for C consumption?

Replying to my own question.

I think I will go with a slightly modified second approach.

The constructor will return BOOL like all the other functions that can fail and will accept a MyClass * out parameter which will be set to some meaningful value even in case of error, so that MyClass_getLastError(myObj) could be used.

This gets rid of the extra MyClass_isInErrorState() function.

MyClass on the C side will be an opaque pointer and on the C++ side will be a pointer to a structure holding a pointer, possibly NULL, to the class' object and a buffer of sorts that contains the error string.

C++ API Wrapper in C for Java/JNA Object references

The code as you've written it will not cause any problems, assuming that you have a native method for releasing the Foo object in C.

What your description seems to be missing is the difference between Java side memory and Native memory. They are separately allocated and handled. Some key points:

  • calling new Foo() inside the C_API_createFoo() function allocates native side memory for that object. You have not shown the code where that memory is released; or any guarantees on how long that object will last. This is not something that happens automatically with Java, and you need to make sure the native API allows you to both persist and dispose of the object when you're done with it.
    • You should probably have C methods corresponding to JNA mappings like dispose(PointerByReference pRef) (or similar) where you can pass the pointer to Foo to release that memory. Some APIs auto-dispose based on a counter when the pointer is accessed and you may need something like keep(PointerByReference pRef) to increment that counter on the native side and make sure it doesn't release that memory too early.
  • The objects you are creating on the Java side are just plain Java objects that will be garbage collected whenever there are no more references to them.
    • In particular, if that object is a PointerByReference or Pointer inside your Java Foo object, it has the value of the native Pointer address, but it doesn't do anything special with that native address when it's GC'd, you have to intentionally do it.
    • To "intentionally" release it (as with any native handle) and avoid handle leaks, I prefer try-with-resources or try-finally blocks.

You don't need to create a Java class just to encapsulate a Pointer. You might prefer to extend the PointerType class (which does exactly that) which gives you a decorated Pointer, e.g.,

class FooHandle extends PointerType() {
}

Then you could change your createFoo() method to:

public FooHandle createFoo(){
PointerByReference pRef = new PointerByReference();
int eC = MyClib.INSTANCE.C_API_createFoo(pRef);
CHECK(eC);
// call code to make sure the native object is persisted
return new FooHandle(pRef.getValue());
}

And as I mentioned you'd need a disposeFoo() method when you're done, to release the native side memory.

For the second example where you are just using a worker, you are not creating a new Foo() object on the native side, you're just calling a "get" method. This implies you're just retrieving a copy of a pointer address, and you can get (pun intended) as many of them as you want, without any problems.

Wrapping array of C objects into C++ class

I'd do it using proposed by You FooRef but a bit differently:

class FooRef {
public:
FooRef (Opaque *o) { self_ = o; }
int f(int a) { return foo_f(self_, a); }
protected:
Opaque *self_;
};

class Foo : public FooRef {
public:
Foo() { self_ = foo_new(); }
//code for copy/move constructor and operator=
~Foo () { foo_delete(self_); }
};

This solution avoids code duplication and allows you to safely return Foo from array. And by the way you got mechanism to simply create FooRef from Foo. Now you can do just:

class FooArray final {
public:
FooRef operator[](const size_t i) {
return FooRef(foo_array_elem(self_, i));
}
private:
OpaqueArray *self_;
};

I think that this should do the trick in elegant way.

Wrapping C++ for use in C#

As a rule, the C/C++ structs are used for communicating with the native code, while you create CLI classes for communicating with the .NET code. C structs are "dumb" in that they can only store data. .NET programmers, on the other hand, expect their data-structures to be "smart". For example:

If I change the "height" parameter in a struct, I know that the height of the object won't actually change until I pass that struct to an update function. However, in C#, the common idiom is that values are represented as Properties, and updating the property will immediately make those changes "live".

That way I can do things like: myshape.dimensions.height = 15 and just expect it to "work".

To a certain extent, the structures you expose to the .NET developer (as classes) actually ARE the API, with the behaviors being mapped to properties and methods on those classes. While in C, the structures are simply used as variables passed to and from the functions that do the work. In other words, .NET is usually an object-oriented paradigm, while C is not. And a lot of C++ code is actually C with a few fancy bits thrown in for spice.

If you're writing translation layer between C and .NET, then a big part of your job is to devise the objects that will make up your new API and provide the translation to your underlying functionality. The structs in the C code aren't necessarily part of your new object hierarchy; they're just part of the C API.

edit to add:

Also to Consider

Also, you may want to re-consider your choice to use C++/CLI and consider C# and p/invoke instead. For various reasons, I once wrote a wrapper for OpenSSL using C++/CLI, and while it was impressive how easy it was to build and how seamless it worked, there were a few annoyances. Specifically, the bindings were tight, so every time the the parent project (OpenSSL) revved their library, I had to re-compile my wrapper to match. Also, my wrapper was forever tied to a specific architecture (either 64-bit or 32-bit) which also had to match the build architecture of the underlying library. You still get architecture issues with p/invoke, but they're a bit easier to handle. Also, C++/CLI doesn't play well with introspection tools like Reflector. And finally, the library you build isn't portable to Mono. I didn't think that would end up being an issue. But in the end, I had to start over from scratch and re-do the entire project in C# using p/invoke instead.

On the one hand, I'm glad I did the C++/CLI project because I learned a lot about working with managed and unmanaged code and memory all in one project. But on the other hand, it sure was a lot of time I could have spent on other things.

template magic for wrapping C callbacks that take void* parameters?

I have discovered a better answer to this question than the other answers given to me here! (Actually it was another engineer inside Google who suggested it).

You have to repeat the function name twice, but that can be solved with a macro.

The basic pattern is:

// Func1, Func2, Func3: Template classes representing a function and its
// signature.
//
// Since the function is a template parameter, calling the function can be
// inlined at compile-time and does not require a function pointer at runtime.
// These functions are not bound to a handler data so have no data or cleanup
// handler.
template <class R, class P1, R F(P1)>
struct Func1 {
typedef R Return;
static R Call(P1 p1) { return F(p1); }
};

// ...

// FuncSig1, FuncSig2, FuncSig3: template classes reflecting a function
// *signature*, but without a specific function attached.
//
// These classes contain member functions that can be invoked with a
// specific function to return a Func/BoundFunc class.
template <class R, class P1>
struct FuncSig1 {
template <R F(P1)>
Func1<R, P1, F> GetFunc() { return Func1<R, P1, F>(); }
};

// ...

// Overloaded template function that can construct the appropriate FuncSig*
// class given a function pointer by deducing the template parameters.
template <class R, class P1>
inline FuncSig1<R, P1> MatchFunc(R (*f)(P1)) {
(void)f; // Only used for template parameter deduction.
return FuncSig1<R, P1>();
}

// ...

// Function that casts the first parameter to the given type.
template <class R, class P1, R F(P1)>
R CastArgument(void *c) {
return F(static_cast<P1>(c));
}

template <class F>
struct WrappedFunc;

template <class R, class P1, R F(P1)>
struct WrappedFunc<Func1<R, P1, F> > {
typedef Func1<R, void*, CastArgument<R, P1, F> > Func;
};

template <class T>
generic_func_t *GetWrappedFuncPtr(T func) {
typedef typename WrappedFunc<T>::Func Func;
return Func().Call;
}

// User code:

#include <iostream>

typedef void (generic_func_t)(void*);

void StronglyTypedFunc(int *x) {
std::cout << "value: " << *x << "\n";
}

int main() {
generic_func_t *f = GetWrappedFuncPtr(
MatchFunc(StronglyTypedFunc).GetFunc<StronglyTypedFunc>());
int x = 5;
f(&x);
}

This is not short or simple, but it is correct, principled, and standard-compliant!

It gets me what I want:

  • The user gets to write StronglyTypedFunc() taking a pointer to a specific thing.
  • This function can be called with a void* argument.
  • There is no virtual function overhead or indirection.


Related Topics



Leave a reply



Submit