2013-3-10 Wrapping C++ exceptions, templated and classes in C
Sometime some libraries is distributed only as C++ libs or in template
code. Or plug-ins for some programs is only in C or other language.
Here can join C and C++ compiled code and there will no big difference
with language you use. Only need to choose right compiler for compilation.
C++ stuff can be easily hidden and you can use some C++ "only" features
in C without notice it.
Use templates from C.
Templates is most C++'sh part of all. Templates are defined in C++ headers
and there not generate code. Only when you use they generate code.
It reason why cannot include them inside *.so or *.a libraries.
But you can always generated templates function examples that will
generate code. And it means it now can be inside *.so and *.a.
To use templates from C and compile it with C we need to hide C++ headers
from C and create templates generated code
C compatible header code.h
extern float cmpx_add_f(float, float); extern int cmpx_add_i( int, int );
C++ template code.hpp
template <typename T> inline T cmpx_add( T a, T b ) { return a+b; }
Tell C++ to generate code for specific templates code.hpp
template int cmpx_add<int>(int, int); template float cmpx_add<float>(float, float);
Write C compatible wrapper in C++
float cmpx_add_f( float a, float b ) { return cmpx_add<float>(a,b); } int cmpx_add_i( int a, int b ) { return cmpx_add<int>(a,b); }
lets see now object file info
readelf -a
18: 0000000000000000 63 FUNC GLOBAL DEFAULT 5 cmpx_add_f
20: 0000000000000000 42 FUNC WEAK DEFAULT 13 _Z8cmpx_addIfET_S0_S0_
21: 000000000000003f 31 FUNC GLOBAL DEFAULT 5 cmpx_add_i
22: 0000000000000000 20 FUNC WEAK DEFAULT 12 _Z8cmpx_addIiET_S0_S0_
We see that functions inside code.h is globally visible and we can use them
without problem from C.
Use C++ exceptions
Exceptions is usually very C++'sh everyone know that exceptions cannot be
used in C. There is some C libraries that add some kind exceptions for
C. That libraries usually uses setjmp and longjmp for simulating that kind of stuff.
C header
extern void raise_exception( int );
C++ code for raising exceptions
extern void raise_exception( int a ) { try { int b; b = b/a; printf("Everything ok ;]\n"); } catch ( int e ) { printf("Catching up exception number %d \n",e); } }
C use exceptions
raise_exception( 1 ); raise_exception( 0 );
Here is seen that C++ exception raises inside C code. There can be made
some code additions and C++ exceptions can be used in C with some tricks.
Not yet proof of concept. But with pointers to functions
(wasn't they called callbacks?) it cone be done.
Use C++ classes
C completable headers
extern void* clA_init(); extern void clA_add( void*,int, int ); extern int clA_empty( void* ); extern void clA_destroy( void* );
C++ class definitions
class A { public: char *p; A(); ~A(); void add( int, int ); bool empty(); };
C++ class implementation
A::A() { this->p = (char *)malloc(1024); } A::~A() { printf("Free Class Baby!!!\n"); if (this->p != NULL) { free( this->p); } } void A::add( int a, int b ) { int i = cmpx_add_i( a , b ); printf("%d\n", i); } bool A::empty() { if (this->p == NULL) { return true; } else { return false; } }
C++ wrapping functions
extern void* clA_init() { A *a = new A; return (void *)a; } extern void clA_add( void *c, int a, int b ) { A *cl=(A*)c; cl->add( a, b ); } extern int clA_empty( void *c ) { A *cl=(A*)c; bool b = cl->empty(); if ( b == true ) { return 1; } else { return 0; } } extern void clA_destroy( void *c ) { A *cl = (A*)c; cl->~A(); }
It easy to give C++ class to C as void* and then use
C++ class functions (wasnt they called methods?) from C
simply as pointers. It segfault oriented but it the way how it works.
These examples shows that you can stay as much as possible with C
and use C++ compiled code.
Links
- http://linux.die.net/man/1/readelf
- http://gcc.gnu.org/codingconventions.html#ExternC
- http://www.cplusplus.com/doc/tutorial/classes/
- http://linux.die.net/man/3/setjmp
- http://linux.die.net/man/3/longjmp