Call a C++ function from a C source code
Is it possible t开发者_高级运维o 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.
- http://developers.sun.com/solaris/articles/mixing.html
- http://developers.sun.com/solaris/articles/external_linkage.html
- http://msdn.microsoft.com/en-us/library/0603949d(VS.80).aspx
- http://www.parashift.com/c++-faq-lite/mixing-c-and-cpp.html#faq-32.6
it's best/easiest to wrap the c++ bits you need in a c interface, then call the c interface from the c source files.
If we're just going to post links, I prefer the FQA to the FAQ.
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::string
s 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.
精彩评论