tags:

views:

175

answers:

5

Hi,

Is it possible to call a C++ function from a C source code?

Please advice.

Many thanks.

+7  A: 

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.

birryree
+1. But you could have copied the code sample: it is small and as long as you give the proper credits (which you did), it's even better.
ereOn
Make sure that no exceptions can come from calling your function, though.
Jack Kelly
Another thing that I've seen trip up other users on SO: the implementation of `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.
Jack Kelly
@Jack Kelly. `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.
Charles Bailey
Anyone know why I am getting an error, error: expected identifier or ‘(’ before string constant
sasayins
@sasayins, can you give us the code in question, perhaps either by editing your question or starting a new question about your compilation error?
birryree
@sasayins: if sharing the headers between the C and C++ builds, you should make sure the extern "C" bit in the headers is surrounded by `#ifdef __cplusplus` / `#endif` so your C compiler doesn't choke on it.
Tony
+3  A: 

If we're just going to post links, I prefer the FQA to the FAQ.

Jack Kelly
"and you can't catch an arbitrary exception and check what kind of exception it is at run time, and operator new can throw exceptions. Enjoy. "
Amigable Clark Kant
The FQA is brilliant. I think the preference of FQA or FAQ classifies programmers very neatly.
Matt Joiner
In addition, the FQA entry on `extern "C"` is *BRUTAL*. C++ needs to stop pretending it's C compatible and move on.
Matt Joiner
+3  A: 

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.

Justin
+1  A: 

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

jrockway
A: 

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.

quamrana