1

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

Please advice.

Many thanks.

domlao
  • 15,663
  • 34
  • 95
  • 134
  • 1
    I wrote a pretty detailed explanation about what you need to d to call OO C++ from C in this post http://stackoverflow.com/questions/2045774/developing-c-wrapper-api-for-object-oriented-c-code/2045860#2045860 – Michael Anderson Oct 12 '10 at 08:58

5 Answers5

9

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.

wkl
  • 77,184
  • 16
  • 165
  • 176
  • 1
    +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 Oct 12 '10 at 06:39
  • Make sure that no exceptions can come from calling your function, though. – Jack Kelly Oct 12 '10 at 06:39
  • 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 Oct 12 '10 at 06:47
  • 2
    @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. – CB Bailey Oct 12 '10 at 07:04
  • Anyone know why I am getting an error, error: expected identifier or ‘(’ before string constant – domlao Oct 12 '10 at 07:07
  • @sasayins, can you give us the code in question, perhaps either by editing your question or starting a new question about your compilation error? – wkl Oct 12 '10 at 07:08
  • 1
    @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 Delroy Oct 12 '10 at 07:34
3

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
  • 104,054
  • 14
  • 179
  • 226
2

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

Jack Kelly
  • 18,264
  • 2
  • 56
  • 81
  • "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. " – Prof. Falken Oct 12 '10 at 08:43
  • 1
    The FQA is brilliant. I think the preference of FQA or FAQ classifies programmers very neatly. – Matt Joiner Oct 13 '10 at 13:50
  • 1
    In addition, the FQA entry on `extern "C"` is *BRUTAL*. C++ needs to stop pretending it's C compatible and move on. – Matt Joiner Oct 13 '10 at 13:52
  • @Matt Joiner: C++ isn't pretending it's C. It's pretending it's a better C. I tend to agree... As for the "exception thing", this is an implementation issue not limited to C/C++ boundaries. It happens between every language boundary: Are you so naive you believe playing with C's setjmp/longjmp (resp. Java's exception) is handled naturally by the Java runtime (resp. C runtime) when mixing C and Java? If you want to link two languages together, then you should be familiar with both. If you are unwilling to, then you deserve whatever comes to you, including bad_alloc exceptions thrown by a new... – paercebal Jul 31 '11 at 22:49
  • 1
    @paercebal: I don't use Java, and I'd never be stupid enough to mix it with C. – Matt Joiner Aug 01 '11 at 00:44
  • 1
    @Matt Joiner: By focusing on the Java/C binding example I gave, you missed the important part, apparently, so I'll repeat it there: `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**. – paercebal Aug 01 '11 at 22:15
2

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
  • 42,082
  • 9
  • 61
  • 86
0

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.

Community
  • 1
  • 1
quamrana
  • 37,849
  • 12
  • 53
  • 71