Is it possible to call a C++ function from a C source code?
Please advice.
Many thanks.
Is it possible to call a C++ function from a C source code?
Please advice.
Many thanks.
You will want to look into the extern C construct.
From the link:
// This is C++ code
// Declare f(int,char,float) using extern "C":
extern "C" void f(int i, char c, float x);
...
// Define f(int,char,float) in some C++ module:
void f(int i, char c, float x)
{
...
}
You can also declare/define multiple functions using the extern C construct are like so:
Declaring and d multiple functions using extern C
extern "C"
{
void func1();
void func2();
}
extern "C"
{
void func1()
{
/// do something
}
void func2()
{
// do something else
}
}
You can even wrap #include declarations with extern "C" like so:
extern "C"
{
#include "myHeader.h"
}
The above will cause everything in fictional header myHeader.h to have C linkage, but can cause problems with nested includes - basically, do not use this construct if you can directly modify the header file yourself. It is a last resort technique.
Caveats
As Jack Kelly (thanks Jack Kelly!) mentions, be sure that if your C++ code involves exceptions, that they are handled in your function and are not allowed to propagate to C.
Functions defined with extern "C" linkage cannot be overloaded, as C does not allow multiple functions with the same name.
Your C and C++ code have to be compiled with similar compilers, as they need to agree on types, calling conventions, etc.
References, because I can't do this alone
Thanks to the commenters.
f needs to be compiled as C code, either by including the header with the extern "C" declaration or by writing it as extern "C" void f(int i, char c, float x) { ... }. Otherwise you get linker errors.extern "C" doesn't mean that the function is compiled as C code, it's still C++ it just has C language linkage. I don't know if this is what you meant, but it's not what you said.#ifdef __cplusplus / #endif so your C compiler doesn't choke on it.extern "C" is BRUTAL. C++ needs to stop pretending it's C compatible and move on.If you want to link two languages together, then you should be familiar with both. This is the real cause of the problem, a cause that FQA's author chose to ignore, preferring instead to condemn C++ as the only guilty party, to feed his maniacal hate against that language. Hating C++ is not a good excuse to F.U.D. it.I needed to do something like this, and saved my experiment to github: http://github.com/jrockway/cplusplus-binding-examples
libexample++ is the C++ library we are trying to bind to C. libexample is the C binding; you compile it with the C++ compiler, but it produces a library with demangled names that C (and everything else) can call. It also converts std::strings to char *s, and so on.
Finally, there is examplehs which is a Haskell binding to libexample, and example-perl, a perl binding to libexample. This lets you see how to call C++ from other languages, via C.
If I was going to do it again, I would have used a different name for the C struct and the C++ class, as the FQA recommends.
(Also, for the sake of "why do it this way", it's because only the C++ compiler knows how to call C++ functions. When you define a function foo, the compiler compiles this to a function that the rest of the runtime toolchain thinks is called something like foo_4dskjaf3874hdfas. This means that only the C++ compiler can generate code that calls it, since only the C++ compiler knows what the function is actually called. When you use extern "C", then the C++ compiler does not "mangle" the name, and then there is no naming problem. You can dlopen the library, call foo, and get the function you expect.
You don't always have to go through C when binding C++ to other languages; Perl will happily invoke the C++ compiler and make it do the demangling, but GHC Haskell won't. So I always go through C when I am trying to bind a C++ library to something, because it's very easy to bind everything else to C. Anything to C++ is hit-or-miss.)
If you want to call functions from C code and you want to #include the header file for the prototype, then the C compile must not see any extern "C" statements.
See other SO questions, eg like this.