Elegantly call C++ from C

Cartesius00 picture Cartesius00 · Sep 2, 2011 · Viewed 36.1k times · Source

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).

Answer

Marcelo Cantos picture Marcelo Cantos · Sep 2, 2011

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); }