Write C wrapper for C++ libraries? - c++

C++11 has sleep_for. But C standard doesn't have the equivalent.
I think I can write a wrapper to call such C++ functions from C.
And there are useful libraries like Boost Filesystem and Asio. These are more complicated but I can also write the wrapper.
Could it be reinventing the wheel? Could it be a bad idea?

An issue with this is, if you want to write C wrappers which call Boost functions, what do you do if an exception is thrown? You basically have to swallow it in the caller before it reaches C, but its a bit awkward to properly report it to C then and there are quite a few types of exceptions.
Usually people use C instead of C++ when they specifically want the extra portability or cannot provide all the C++ dependencies for some reason. If you want to write a C program that uses boost::filesystem, why not just compile it as C++? You will have a lot less exception handling boiler plate code to write, and less can go wrong.

zeroMQ does it that way. The library is written in C++, but the library API is a C interface. In principle, you hide classes in memory blocks of the object size and pass void* around. For a few simple function, e.g. sleep_for, you can just create a wrapper function. In your header, declare
extern "C" {void sleep_for(int duration);}
In your cpp-file, implement this in terms of std::this_thread::sleep_for.
sleep_for(int duration) {std::this_thread::sleep_for( std::chrono::milliseconds(duration);}
For classes, you need C function to create a new object, destruct it and of course to call member functions. For a class A, this could look as follows:
C header file "A_C_API.h":
extern "C" {
enum {SIZE_OF_A = 4};
typedef char[SIZE_OF_A] a_class;
a_class initA(void* a, int x);
void destructA(void* a);
int callGet(void *a);
}
C++ source file:
class A {
public:
A(int i): x{i} {}
int get() const {return x;}
private:
int x;
};
static_assert( SIZE_OF_A == sizeof(A), "size mismatch!");
void initA(void* a, int x) {
new (a) A(x);
}
void destructA(void* a) {
static_cast<A*>(a)->~A();
}
int callGet(void *a) {
return static_cast<A*>(a)->get();
}
In your C application, you can then
#include "A_C_API.h"
int main(int argc, char* argv[]) {
a_class obj;
initA(&obj);
printf("%d", callGet(&obj) );
destructA( &obj );
return 0;
}
You will have to catch exceptions and convert them to some C error handling. You will also have to handle alignment issues on some platforms, especially SPARK platforms. I have omitted this for simplicity, but you can take a look at the zeromq header how to do this.

Related

How can I expose C++ function pointers in C?

I have two types of function pointers defined in my C++ that look like this:
typedef void(*CallbackFn)(bool, std::string, py::array_t<uint8_t>&);
typedef std::function<void(std::string)> LogFunction;
Class Core{
...
void myfunc1(LogFunction lg1, CallbackFn callback, int x, std::string y);
};
and I want to be able to expose them in C but I can't seem to find a way to do so. My first try was to cast these as void* and then recast them back to their actual type. but this seems like a bad idea. So I'm clueless as how to go about this conversion.
Also the solution that I need to come-up with should be doable using C++11 at the very least.
Update:
Thank you very much for your answers. However I need to add a bit more explanation as what I'm after. I know about extern "C" and in fact the C++ functions are exposed using this already in my DLL. However, the problem I had was to pass the function pointers back and forth between the C and C++.
One way was to define function pointers in a way that can be directly usable by C. That is I needed to change for example :
typedef void(*CallbackFn)(bool, std::string, py::array_t<uint8_t>&);
typedef std::function<void(std::string)> LogFunction;
to its C compatible one :
typedef void(*CCallbackFn)(bool, char*, int, unsigned char, int length);
typedef void(*CLogFunction)(char* string, int length);
and use these instead. However, the disadvantage of doing this is that, the DLL is also used by C++ clients and this would be a hindrance to change everything C++ to be compatible by C, I'd lose the advantages of C++ by doing this.
Instead I though of coming up with a second way. The C++ stays the same, but for C linkage and interacting with other languages through C API, I do the conversion myself.
That is they use C style and then I convert this back to C++ in the implementation part. In order to further simplify this so I designed some defaults on C++ part as well. Meaning, suppose for the lack of a better example, the instance needs a callback function to log whatever happens. I define a callback function in case it was not given by the user and create two functions for C API specifically something roughly similar to this:
//in core.cpp for example
include "Core.h"
...
extern "C"
{
Core * core;
...
Core_API void* get_default_log_callback()
{
return (void*) core->SomeDefaultCallback();
}
Core_API void* set_log_callback(void* fn)
{
// convert/cast that to the c++ callback type
// CallbackFn,
core->SetCallback(fn_converted);
}
and the client could for example use the get_default_log_callback and use its return to set_log_call_back.
Basically the idea here is to be able to use the C++ already defined assets.
I was stuck at this conversion process, how to convert such callback pointers to a C compatible type ( like what I showed, it'd be really easy to just cast the pointer to void* for example and write a C wrapper that accepts void* and then recast it to the proper type.
I'd like to know about this scenario as well and whether this is a good practice or the otherwise a bad one.
Question two:
Also I'd like to know if it is possible to have a conversion from for example the CCallbackFn and CallbackFn?
Suppose I've got a function(my C function above e.g.) in a CCalbackFn form ,but I want to ultimately have it in CallbackFn form(change it and call the underlying C++ that accepts CallbackFn) ? is this possible ?
C doesn't do / cannot handle C++ name mangling (nor C++ types that are not identical to C types). You cannot use non-POD types (and plain function pointers involving types not usable in C) in anything exposed to C. And you need to use extern "C" for the exposed stuff, to disable name mangling (or rather, use whatever naming convention/mangling your current platforms C compiler uses).
In short: use extern "C" for anything that must be callable from C and make sure anything exposed that way only uses types that you can write/use in C.
You can expose a function to C by declaring it extern "C".
However, the function must only accept argument types that are valid in C.
From the look of the code above, you're going to have to express your callback in more C-like terms.
In order to expose any C++ functions to C, you should wrap the C++ calls in C functions in a plain C++ library. And export only the C functions from it. Use a common header for C functions declarations inside and outside the library. These functions will be callable from any C environment. All the C++ types wrap in a class and pass a pointer to that class across function wrappers, as a handle to C++ environment. The pointer to class should be void* or just long. And only in C++ side you will reinterpret it to own environment class.
Update 1:
You should keep C and C++ separated. It means don't do conversions between C and C++. Keep separated C versions and C++ versions of XX_log_callback functions. For instance your C++ functions uses std::string, py::array_t&. There is no way you can use it is C. No conversion available, and no way to take advantages of it in C. You can take advantage of C++ only in C++, so make a separate version for C++ only and one available for C developers.
This is a by the way. There is a technique of passing around C++ interfaces to C and back to C++. But be attentive, it uses only C compatible return and argument types. It means creating a structure with a pointer to a table of function pointers. In C++ it is an interface but in C it is a struct. This technique is used in COM/OLE2 in Windows. https://www.codeproject.com/Articles/13601/COM-in-plain-C To use such a technique you should understand very well how to make a C++ class compatible with a C struct.
Now I will just copy/paste some pieces of code from the codeproject with little explanations.
The rule of thumb when passing interfaces between C and C++, use only types compatible with C as function arguments and as return type. The first four bytes in the interface is a pointer to an array of functions, called Virtual Table:
typedef struct
{
IExampleVtbl * lpVtbl;//<-- here is the pointer to virtual table
DWORD count;//<-- here the current class data starts
char buffer[80];
} IExample;
Here you add the pointers to functions in the virtual table. The IExampleVtbl is a structure filled with pointers, and binary it is equivalent to a contiguous array of pointers
static const IExampleVtbl IExample_Vtbl = {SetString, GetString};
IExample * example;
// Allocate the class
example = (IExample *)malloc(sizeof(IExample));
example->lpVtbl = &IExample_Vtbl;//<-- here you pass the pointer to virtual functions
example->count = 1; //<-- initialize class members
example->buffer[0] = 0;
Now this is how you call the methods:
char buffer[80];
example->lpVtbl->SetString(example, "Some text");
example->lpVtbl->GetString(example, buffer, sizeof(buffer));
Keep in mind, all of above is C.
In the above example you refer explicitly the virtual table member, and also you pass it explicitly as first parameter in the functions. The C++ equivalent of call to GetString/SetString is:
example->SetString("Some text");
example->GetString(buffer, sizeof(buffer));
Here is the SetString/GetStrinf functions and the virtual table structure:
HRESULT STDMETHODCALLTYPE SetString(IExample *this, char * str)
{
memcpy(this->buffer, str, length);//be attentive, it is almost pseudocode
return(0);
}
HRESULT STDMETHODCALLTYPE GetString(IExample *this, char *buffer, int buffer_len)
{
memcpy(str, this->buffer, length);//be attentive, it is almost pseudocode
return(0);
}
typedef struct {
SetStringPtr *SetString;
GetStringPtr *GetString;
} IExampleVtbl;
The STDMETHODCALLTYPE is to make it compatible with C++ calling of member function classes, so you will be able to pass the IExample between C and C++. I believe this will be really a nightmare for the C programmers, but not an easy task for C++ counterparts.
To access that when interface is passed from C, you declare interface like this:
class IExample
{
public:
virtual HRESULT SetString(char * str) = 0;//<-- see first parameter gone away in both functions
virtual HRESULT GetString(char *buffer, int buffer_len) = 0;
};
If you implement in C++ to pass in C equivalent of above code will be:
class IExample
{
int count = 1; //<-- initialize class members
char buffer[80] = "";
public:
virtual HRESULT SetString(char * str)
{
memcpy(this->buffer, str, length);//be attentive, it is almost pseudocode
return(0);
}
virtual HRESULT GetString(char *buffer, int buffer_len)
{
memcpy(str, this->buffer, length);//be attentive, it is almost pseudocode
return(0);
}
};
One more thing. You don't use the C declaration in C++ and vice-versa. This is by the COM approach to address the issue. It might be not portable to different compilers but keep in mind, similar approach is done in the old CORBA. Only you should keep in mind. You create one interface for C and one for C++. On C++ part hide the C interface and on C hide the C++ interface. Pass around only the pointers.
I ultimately came up with my own solution which I myself refer to as "Delegating Callbacks" approach! The idea here is that, instead of directly use the C callback, you create a diversion, you create an intermediate callback that acts as a translator between the two APIs.
For example, suppose my C++ class has a method that accepts only callbacks with this signature :
typedef void(*CallbackFn)(bool, std::string, py::array_t<uint8_t>&);
And now we want to expose this to C. and this is our C callback signature :
typedef void(*CCallbackFn)(bool, const char*, unsigned char*, int rows, int cols);
Now how do we go from the first to the second one or vice versa? We create a new callback in our C++ class of type CallbackFn, and inside it execute the C callbacks. So using an indirect call, we can easily decouple the signatures between the C and C++ APIs and use the ones that are most suitable for each.
To make it more concrete we need to have something like this:
CORE_API void Core::DelegateCCallback(bool status, std::string id, py::array_t<uint8_t>& img)
{
//here is used a std::map to store my c-callbacks you can use
//vector or anything else that you like
for (auto item: this->callbackMap_c)
{
//item.first is our callback, so use it like a function
item.first(status, id.c_str(), img.mutable_data(), img.shape(0), img.shape(1));
}
}
And you update your C callback list like this, using two exposed functions, Add and Remove to add and remove any callbacks respectively :
extern "C"
{
//Core is our C++ class for example
Core* core = nullptr;
...
CORE_API void AddCallback(CCallbackFn callback)
{
core->AddCallback_C(callback);
}
CORE_API void RemoveCallback(CCallbackFn callback)
{
core->RemoveCallback_C(callback);
}
}
and back in our C++ class, AddCallback_C methods are defined like:
CORE_API void Core::AddCallback_C(CCallbackFn callback)
{
auto x = this->callbackMap_c.emplace(callback, typeid(callback).name());
}
CORE_API void Core::RemoveCallback_C(CCallbackFn callback)
{
this->callbackMap_c.erase(callback);
}
Just adding/removing the callback to the callback list. That's all.
Now when we instantiate our C++ Code, we need to add the DelegateCCallback to the callback list, so when all C++ callbacks are executed this one executes too and with it, it will loop through all the C callbacks and executes them one by one.
For example in my case, the callbacks needed to be run in a Python module, so in my constructor I had to do something like this:
CORE_API Core::Core(LogFunction logInfo)
{
//....
// add our 'Callback delegate' to the list of callbacks
// that would run.
callbackPyList.attr("append")(py::cpp_function([this](bool status, std::string id, py::array_t<uint8_t>& img)
{
this->DelegateCCallback(status, id, img);
}));
//...
}
You can get fancy with this and incorporate threads, etc as you wish.

How to call c-style cleaner functions implicitly?

I am working on some c Apis and I always have to check some variables are initialized and then clear/destroy/free them using special functions. such as allocation :
ogg_stream_state os;
ogg_stream_init(&os,ogg_page_serialno(&og));
and destroying:
ogg_stream_clear(&os);
I want to call the cleaner function automatically and not explicitly.
Using C++ Templates you can do it easily:
template<typename ARG, typename RET>
class Destroyer
{
public:
typedef RET (*DestoyerFn)(ARG*);
Destroyer(DestoyerFn destroyer_fn, ARG* object_ptr) { objectPointer = object_ptr; destroyerFn = destroyer_fn;}
~Destroyer()
{
if(destroyerFn && objectPointer)
destroyerFn(objectPointer);
}
private:
DestoyerFn destroyerFn;
ARG* objectPointer;
};
ARG is the argument of your cleaner function, and RET is the return type of that (RET needed to avoid compiler warning.)
example call:
Destroyer<ogg_stream_state, int> des_ogg_stream(ogg_stream_clear, &os);
now every where you like, just return from your function, it will call your cleaner function.
In a real-world scenario you most likely want some kind of custom wrapper around the C functions, to encapsulate them and to dodge C like behavior and oddities such as calling convention.
In the real world, I don't believe you can treat any C code as "a generic C API" and design some template class which can handle all possible C APIs. There are far too many things to consider to make such a generic class feasible.
For example, given the following random C code:
//cfile.c
static int* something;
void cfunction_init (void)
{
printf("C function init\n");
something = (int*) malloc(sizeof(*something));
}
void cfunction_cleanup (void)
{
printf("C function cleanup\n");
free(something);
}
You can make a wrapper class like this:
class wrapper
{
public:
wrapper() { cfunction_init(); }
~wrapper() { cfunction_cleanup(); }
};
Then simply declare a wrapper class variable at the appropriate scope:
#include <iostream>
int main()
{
wrapper w;
std::cout << "C++ program executing" << std::endl;
return 0;
}
Program output:
C function init
C++ program executing
C function cleanup
I'd consider wrapping ogg_stream_state with a shared_ptr with custom destructor.
class OggStreamState {
public:
shared_ptr<ogg_stream_state> state;
OggStreamState() :
state(new ogg_stream_state, &ogg_stream_clear)
{}
};
Your code would now look like this:
OggStreamState os;
ogg_stream_init(os.state.get(),ogg_page_serialno(&og));
Which is a little ugly, but this technique gives a logical place to start moving to an object oriented interface rather than a C function based one.
For example you could then move ogg_stream_init into OggStreamState so that it would become
OggStreamState os;
os.init(ogg_page_seialno(&og));
Take it one step further and repeat for the ogg_page, and you'd get
OggPage og = ...;
OggStreamState os;
os.stream_init(og.serialno());
You could even pull the init all the way into the constructor
OggStreamState os(og.serialno());
or at the extreme...
OggStreamState os(og);
Another advantage of this over a pure sentry RAII (like the solution from Lundin) is that you can pass the OggStreamState in and out of functions with out trouble. The compiler will determine when your last reference is destroyed and call the clear function for you. i.e. you can safely have a
OggStreamState oss = function_that_returns_a_stream_state(...);
Of course this technique does introduce other overheads, but usually they are minimal - also it does blur the ownership of the ogg stream slightly, which many or may not be a good thing...

Elegantly call C++ from C

We develop some project in plain C (C99). But, we have one library as source codes (math library) in C++. We need this library so I would like to ask, what is the most elegant way to integrate this source codes?
Ratio between sizes of C and C++ is 20:1 so moving to C++ is not the option. Should we use static library? DLL? (It's all on Windows).
EDIT: Based on discussion in the comment, I should point out that separating things into a C-compatible struct duck and a derived class Duck is probably unnecessary. You can probably safely shovel the implementation into struct duck and eliminate class Duck, thus obviating real(…). But I don't know C++ well enough (in particular, the way it interacts with the C universe) to offer a definitive answer on this.
There is no reason you can't simply link all your C and C++ code together into a single binary.
Interfacing to the C++ code requires that you wrap the C++ API in a C API. You can do this by declaring a bunch of functions inside extern "C" { ... } when compiling the C++ code, and without the extern declaration when compiling the C client code. E.g.:
#ifdef __cplusplus
extern "C" {
#endif
typedef struct duck duck;
duck* new_duck(int feet);
void delete_duck(duck* d);
void duck_quack(duck* d, float volume);
#ifdef __cplusplus
}
#endif
You can define the duck struct in your C++ source, and even inherit the real Duck class from it:
struct duck { };
class Duck : public duck {
public:
Duck(int feet);
~Duck();
void quack(float volume);
};
inline Duck* real(duck* d) { return static_cast<Duck*>(d); }
duck* new_duck(int feet) { return new Duck(feet); }
void delete_duck(duck* d) { delete real(d); }
void duck_quack(duck* d, float volume) { real(d)->quack(volume); }
The only reason to want to inherit from the duck struct would be to expose some to its attributes in the C API, which is generally considered bad style anyway. Without inheritance, your C header would look like this:
struct Duck;
struct Duck* new_Duck(int feet);
void delete_Duck(struct Duck* d);
void Duck_quack(struct Duck* d, float volume);
And this would be the corresponding implementation, with no need for type casts:
extern "C" {
#include "Duck.h"
}
class Duck {
public:
Duck(int feet) : {}
~Duck() {}
void quack(float volume) {}
};
struct Duck* new_Duck(int feet) { return new Duck(feet); }
void delete_Duck(struct Duck* d) { delete d; }
void Duck_quack(struct Duck* d, float volume) { d->quack(volume); }
In the same way, a C API can be created for a C++ interface (pure virtual class) and its implementations. In that case, only the constructor need to be based on the concrete implementation (e.g. new_RubberDuck(2)). The destructor and all other functions will automatically operate on the correct implementation, same as in C++.
A C++ math library may well be implemented in the for of utility classes (static members only). In this case, a much simpler approach could be taken:
class FPMath {
public:
static double add(double, double);
static double sub(double, double);
static double mul(double, double);
static double div(double, double);
};
The header for the C interface would then be:
double FPMath_add(double, double);
double FPMath_sub(double, double);
double FPMath_mul(double, double);
double FPMath_div(double, double);
And the corresponding implementation might be:
double FPMath_add(double a, double b) { return FPMath::add(a, b); }
double FPMath_sub(double a, double b) { return FPMath::sub(a, b); }
double FPMath_mul(double a, double b) { return FPMath::mul(a, b); }
double FPMath_div(double a, double b) { return FPMath::div(a, b); }
But maybe this is stating the obvious....
There is a way to create a "hack" that allows you to call member functions of some objects directly.
The first thing you have to do is to create an extern "C" factory function, which returns a pointer (as void*) to the object.
The second thing you need is the mangled name of the member function.
Then you can call the function using the mangled name, and passing the pointer returned from the factory function as the first argument.
Caveats:
Will of course not work calling member function that wants other objects, or references, or other C++ stuff, or functions returning objects or types not compatible with C types
Will not work on virtual member functions, and probably not on objects with virtual functions in them even if it's not a virtual function being called
The mangled name have to be a valid C symbol
Any many many more...
This is not something I recommend, quite the opposite in fact. I strongly advise against doing something like outlined in this answer. It's unsupported and probably undefined behavior and may break in weird and unpredictable ways.

Writing a C++ wrapper for a C library

I have a legacy C library, written in an OO type form. Typical functions are like:
LIB *lib_new();
void lib_free(LIB *lib);
int lib_add_option(LIB *lib, int flags);
void lib_change_name(LIB *lib, char *name);
I'd like to use this library in my C++ program, so I'm thinking a C++ wrapper is required.
The above would all seem to map to something like:
class LIB
{
public:
LIB();
~LIB();
int add_option(int flags);
void change_name(char *name);
...
};
I've never written a C++ wrapper round C before, and can't find much advice about it. Is this a good/typical/sensible approach to creating a C++/C wrapper?
A C++ wrapper is not required - you can simply call the C functions from your C++ code. IMHO, it's best not to wrap C code - if you want to turn it into C++ code - fine, but do a complete re-write.
Practically, assuming your C functions are declared in a file called myfuncs.h then in your C++ code you will want to include them like this:
extern "C" {
#include "myfuncs.h"
}
in order to give them C linkage when compiled with the C++ compiler.
I usually only write a simple RAII wrapper instead of wrapping each member function:
class Database: boost::noncopyable {
public:
Database(): handle(db_construct()) {
if (!handle) throw std::runtime_error("...");
}
~Database() { db_destruct(handle); }
operator db_t*() { return handle; }
private:
db_t* handle;
};
With the type conversion operator this can be used with the C functions:
Database db;
db_access(db, ...); // Calling a C function with db's type conversion operator
I think it only makes sense to write a wrapper if it makes the use of the library simpler. In your case, you're making it unnecessary to pass a LIB* around, and presumably it will be possible to create LIB objects on the stack, so I'd say this is an improvement.
That's generally how I would approach it. I would also not use char* but use std::string.
A C++ wrapper is not needed per se. There's nothing stopping you from calling the C functions in your code.
I'd also look at renaming LIB to something a bit better, if nothing else "Lib"
Change Name is likely to be a getter setter...
so GetName(char *) SetName(char *)
and then look at changing it to std::string instead of char*, if its SetName(const std::string name) it will accept a char* as a parameter.
ie, slowly move to C++isms
Assuming that the C library's allocation/deallocation instances are create_instance and destroy_instance, and it exposes a function called call_function, and it does not provide an API for deep copying instances, this will work:
class Wrapper
{
public:
Wrapper(): m_instance(create_instance(), destroy_instance) {}
explicit operator bool() const
{
// null check
return bool(m_instance);
}
void callFunction()
{
call_function(m_instance.get());
}
private:
std::unique_ptr<instance, decltype(&destroy_instance)> m_instance;
};

Wrapping C++ class API for C consumption

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);
}
While Loki Astari's answer is very good, his sample code puts the wrapping code inside the C++ class. I prefer to have the wrapping code in a separate file. Also I think it is better style to prefix the wrapping C functions with the class name.
The following blog posts shows how to do that:
http://blog.eikke.com/index.php/ikke/2005/11/03/using_c_classes_in_c.html
I copied the essential part because the blog is abandoned and might finally vanish (credit to Ikke's Blog):
First we need a C++ class, using one header file (Test.hh)
class Test {
public:
void testfunc();
Test(int i);
private:
int testint;
};
and one implementation file (Test.cc)
#include <iostream>
#include "Test.hh"
using namespace std;
Test::Test(int i) {
this->testint = i;
}
void Test::testfunc() {
cout << "test " << this->testint << endl;
}
This is just basic C++ code.
Then we need some glue code. This code is something in-between C and C++. Again, we got one header file (TestWrapper.h, just .h as it doesn't contain any C++ code)
typedef void CTest;
#ifdef __cplusplus
extern "C" {
#endif
CTest * test_new(int i);
void test_testfunc(const CTest *t);
void test_delete(CTest *t);
#ifdef __cplusplus
}
#endif
and the function implementations (TestWrapper.cc, .cc as it contains C++ code):
#include "TestWrapper.h"
#include "Test.hh"
extern "C" {
CTest * test_new(int i) {
Test *t = new Test(i);
return (CTest *)t;
}
void test_testfunc(const CTest *test) {
Test *t = (Test *)test;
t->testfunc();
}
void test_delete(CTest *test) {
Test *t = (Test *)test;
delete t;
}
}
First, you might not need to convert all your methods to C functions. If you can simplify the API and hide some of the C++ interface, it is better, since you minimize the chance to change the C API when you change C++ logic behind.
So think of a higher level abstraction to be provided through that API. Use that void* solution you described. It looks to me the most appropriate (or typedef void* as HANDLE :) ).
Some opinions from my experience:
functions should return codes to represent errors. It's useful to have a function returning error description in string form. All other return values should be out parameters.
E.g.:
C_ERROR BuildWidget(HUI ui, HWIDGET* pWidget);
put signatures into structures/classes your handles pointer to for checking handles on validness.
E.g. your function should look like:
C_ERROR BuildWidget(HUI ui, HWIDGET* pWidget){
Ui* ui = (Ui*)ui;
if(ui.Signature != 1234)
return BAD_HUI;
}
objects should be created and released using functions exported from DLL, since memory allocation method in DLL and consuming app can differ.
E.g.:
C_ERROR CreateUi(HUI* ui);
C_ERROR CloseUi(HUI hui); // usually error codes don't matter here, so may use void
if you are allocating memory for some buffer or other data that may be required to persist outside of your library, provide size of this buffer/data. This way users can save it to disk, DB or wherever they want without hacking into your internals to find out actual size. Otherwise you'll eventually need to provide your own file I/O api which users will use only to convert your data to byte array of known size.
E.g.:
C_ERROR CreateBitmap(HUI* ui, SIZE size, char** pBmpBuffer, int* pSize);
if your objects has some typical representation outside of your C++ library, provide a mean of converting to this representation (e.g. if you have some class Image and provide access to it via HIMG handle, provide functions to convert it to and from e.g. windows HBITMAP). This will simplify integration with existing API.
E.g.
C_ERROR BitmapToHBITMAP(HUI* ui, char* bmpBuffer, int size, HBITMAP* phBmp);
Use vector (and string::c_str) to exchange data with non C++ APIs. (Guideline #78 from C++ Coding Standards, H. Sutter/ A. Alexandrescu).
PS It's not that true that "constructors can retain their original argument list". This is only true for argument types which are C-compatible.
PS2 Of course, listen to Cătălin and keep your interface as small and simple as possible.
This may be of interest: "Mixing C and C++" at the C++ FAQ Lite. Specifically [32.8] How can I pass an object of a C++ class to/from a C function?