main.lv
Dont think code it

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


Downloads

c_cpp_tricks.tar.gz2KiB