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).
Accessing C++ Code from Within C SourceIf you declare a C++ function to have C linkage, it can be called from a function compiled by the C compiler. A function declared to have C linkage can use all the features of C++, but its parameters and return type must be accessible from C if you want to call it from C code.
extern "C" is a linkage specification which is used to call C functions in the Cpp source files. We can call C functions, write Variables, & include headers. Function is declared in extern entity & it is defined outside.
Code structure of both the languages are same. The compilation of both the languages is similar. They share the same basic syntax. Nearly all of C's operators and keywords are also present in C++ and do the same thing.
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++.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With