Tutorial: HowTo integrate a C++ library/class into a C programm
Emagine the situation: You have written a program in C and now you have the requirement to integrate an existing third parity C++ library into your program.
The C++ Library
The only thing you have is the class definition in the header file of the library:
MyClass.h |
#ifndef __MYCLASS_H #define __MYCLASS_H class MyClass { private: int m_i; public: void int_set(int i); int int_get(); }; #endif |
It is a simple class with only one member variable m_i and one setter and one getter method.
Perhaps you don't have the source code of the library, perhaps you only have a compiled version. To be able to reproduce the example here is the source of the class:
MyClass.cc |
#include "MyClass.h" void MyClass::int_set(int i) { m_i = i; } int MyClass::int_get() { return m_i; } |
To compile the class with GNU C++ comiler simply type:
g++ -c MyClass.cc -o MyClass.o |
This gives you the object file that can be linked into your programm. In this place I won't explain how to create a complete library.
The C++ way
Just for comparison here a simple C++ program that uses our new class:
MyMain_c++.cc |
#include "MyClass.h" #include <iostream> using namespace std; int main(int argc, char* argv[]) { MyClass *c = new MyClass(); c->int_set(3); cout << c->int_get() << endl; delete c; } |
This program can be compiled with:
g++ -c MyMain_c++.cc -o MyMain_c++.o |
And linked with:
g++ MyMain_c++.o MyClass.o -o MyMain_c++ |
Start the C++ program with:
./MyMain_c++ |
The Problem
If we want to access a C++ library from C code we have two problems that we have to solve:
- The name mangling of C is differnt to C++.
- C doesn't know classes.
The C-Wrapper
To solve these problems we have to write a C-wrapper around our C++ class. Our wrapper header file will be readable by the C and the C++ compiler.
MyWrapper.h |
#ifndef __MYWRAPPER_H #define __MYWRAPPER_H #ifdef __cplusplus extern "C" { #endif typedef struct MyClass MyClass; MyClass* newMyClass(); void MyClass_int_set(MyClass* v, int i); int MyClass_int_get(MyClass* v); void deleteMyClass(MyClass* v); #ifdef __cplusplus } #endif #endif |
The extern "C" {} statement tells the C++ compiler to use the C style name mangling so a C compiler will find the correct symbols in the object file later. The #ifdef __cplusplus contition is because the C compiler does not know the keyword extern.
For the C compiler we define a dummy class handler with typedef struct MyClass MyClass.
And then the constructor, method and destructor wrappers.
The following file is the wrapper code, written in C++, but with one important thing: it is defined as extern "C"!
MyWrapper.cc |
#include "MyClass.h" #include "MyWrapper.h" extern "C" { MyClass* newMyClass() { return new MyClass(); } void MyClass_int_set(MyClass* v, int i) { v->int_set(i); } int MyClass_int_get(MyClass* v) { return v->int_get(); } void deleteMyClass(MyClass* v) { delete v; } } |
To compile the wrapper with GNU C++ comiler simply type:
g++ -c MyWrapper.cc -o MyWrapper.o |
The C Program
Now we are ready to use the C++ class in our C code:
MyMain_c.c |
#include "MyWrapper.h" #include <stdio.h> int main(int argc, char* argv[]) { struct MyClass* c = newMyClass(); MyClass_int_set(c, 3); printf("%i\n", MyClass_int_get(c)); deleteMyClass(c); } |
This program can be compiled with the C compiler:
gcc -c MyMain_c.c -o MyMain_c.o |
Note that the linking has to be done with the C++ comiler, a C linker like ldd does not work:
g++ MyMain_c.o MyWrapper.o MyClass.o -o MyMain_c |
Start the C program with:
./MyMain_c |
You should now get the same result as with your C++ program above.
I hope this mini tutorial helped you.