I have a set of related C++ classes which must be wrapped and exported from a DLL in such a way that it can be easily consumed by C / FFI libraries. I'm looking for some "best practices" for doing this. For example, how to create and free objects, how to handle base classes, alternative solutions, etc...
Some basic guidelines I have so far is to convert methods into simple functions with an extra void* argument representing the 'this' pointer, including any destructors. Constructors can retain their original argument list, but must return a pointer representing the object. All memory should be handled via the same set of process-wide allocation and free routines, and should be hot-swappable in a sense, either via macros or otherwise.
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);
}