117

I have a C++ library that provides various classes for managing data. I have the source code for the library.

I want to extend the C++ API to support C function calls so that the library can be used with C code and C++ code at the same time.

I'm using GNU tool chain (gcc, glibc, etc), so language and architecture support are not an issue.

Are there any reasons why this is technically not possible?

Are there any gotcha's that I need to watch out for?

Are there resources, example code and/or documentation available regarding this?


Some other things that I have found out:

  1. Use the following to wrap your C++ headers that need to be used by C code.

#ifdef __cplusplus
extern "C" {  
#endif  
//  
// Code goes here ...  
//  
#ifdef __cplusplus  
} // extern "C"  
#endif
  1. Keep "real" C++ interfaces in separate header files that are not included by C. Think PIMPL principle here. Using #ifndef __cplusplus #error stuff helps here to detect any craziness.
  2. Careful of C++ identifiers as names in C code
  3. Enums varying in size between C and C++ compilers. Probably not an issue if you're using GNU tool chain, but still, be careful.
  4. For structs follow the following form so that C does not get confused.

    typedef struct X { ... } X
    
  5. Then use pointers for passing around C++ objects, they just have to be declared in C as struct X where X is the C++ object.

All of this is courtesy of a friend who's a wizard at C++.

Misha M
  • 10,979
  • 17
  • 53
  • 65
  • 8
    Somewhat late, but I wrote a small howto about C wrapper for C++: http://www.teddy.ch/c++_library_in_c/ – Teddy Jul 20 '15 at 20:09

4 Answers4

78

Yes, this is certainly possible. You will need to write an interface layer in C++ that declares functions with extern "C":

extern "C" int foo(char *bar)
{
    return realFoo(std::string(bar));
}

Then, you will call foo() from your C module, which will pass the call on to the realFoo() function which is implemented in C++.

If you need to expose a full C++ class with data members and methods, then you may need to do more work than this simple function example.

Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
  • 1
    Should `extern "C"` be placed only in declarations (and not in definitions)? Because you mentioned "the layer that declares functions" but your sample code is also a definition. In other words, should we place it in header files or source files?(or both?) – kyriakosSt Oct 15 '17 at 17:40
  • @KyrSt: If you have a header file with a function declaration, then you have to at least put `extern "C"` there. Your compiler will tell you if you also have to put it on the definition. – Greg Hewgill Oct 16 '17 at 03:15
26

C++ FAQ Lite: "How to mix C and C++ code".

Some gotchas are described in answers to these questions:

  • [32.8] How can I pass an object of a C++ class to/from a C function?
  • [32.9] Can my C function directly access data in an object of a C++ class?
omninonsense
  • 6,644
  • 9
  • 45
  • 66
Alex B
  • 82,554
  • 44
  • 203
  • 280
13

Main gotcha: exceptions can not be caught in C. If there is the possibility of an exception rising in the C++ code, either write your C code or your C++ wrappers very carefully. Conversely, exception like mechanisms (i.e., longjump) in the C code (as found in various scripting languages) are not required to invoke destructors for C++ objects on the stack.

ejgottl
  • 2,809
  • 19
  • 18
  • 2
    Great point about longjump calls. While I don't use them directly, the testing frameworks that I use do implement them. Something to keep in mind. Thanks – Misha M Oct 14 '08 at 00:04
3

you can mix C/C++ code. If your main() function in in C++, then you just need to make sure your c functions are declared

extern "C"

If your main is C, then you are probably OK except for static variables. Any constructors with your static variables are supposed to be called before main() start. This won't happen if C is your main. I you have a lot of static variables, the best thing to do is to replace static variables with singletons.

David Nehme
  • 21,379
  • 8
  • 78
  • 117