Elegantly call C++ from C Elegantly call C++ from C c c

Elegantly call C++ from C


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 __cplusplusextern "C" {#endiftypedef 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....