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:
- Every object is passed about in C an opaque handle.
- Constructors and destructors are wrapped in pure functions
- Member functions are pure functions.
- 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++.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…