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

Downloads

c_cpp_tricks.tar.gz - 2KiB - http://archive.main.lv/files/writeup/wrapping_c___exceptions,_templated_and_classes_in_c/c_cpp_tricks.tar.gz