1

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

Please advice.

Many thanks.

1

5 Answers 5

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.

Sign up to request clarification or add additional context in comments.

7 Comments

+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.
Make sure that no exceptions can come from calling your function, though.
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. 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.
@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.
|
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.

Comments

2

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

6 Comments

"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. "
The FQA is brilliant. I think the preference of FQA or FAQ classifies programmers very neatly.
In addition, the FQA entry on extern "C" is BRUTAL. C++ needs to stop pretending it's C compatible and move on.
@paercebal: I don't use Java, and I'd never be stupid enough to mix it with C.
@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.
|
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.)

Comments

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.