summaryrefslogblamecommitdiffstats
path: root/md/writeup/wraping_c_plus_plus_exceptions_templates_and_classes_in_c.md
blob: 0f43f21e60fd858edb746ec04e93c412c6211493 (plain) (tree)











































































































































































































































                                                                                                                      
title:Wrapping C++ exceptions, templated and classes in C
keywords:c++,c,exeptions,templates,classes

# 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

```c
extern float cmpx_add_f(float, float);
extern int   cmpx_add_i( int, int );
```

C++ template code.hpp

```c
template <typename T>
inline T cmpx_add( T a, T b )
{
    return a+b;
}
```

Tell C++ to generate code for specific templates code.hpp

```c
template int cmpx_add<int>(int, int);
template float cmpx_add<float>(float, float);
```

Write C compatible wrapper in C++

```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
```

```c
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

```c
extern void  raise_exception( int );
```

C++ code for raising exceptions

```c
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

```c
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

```c
extern void* clA_init();
extern void  clA_add( void*,int, int );
extern int   clA_empty( void* );
extern void  clA_destroy( void* );
```

C++ class definitions

```c
class A
{
    public:
        char *p;
        A();
        ~A();
        void add( int, int );
        bool empty();
};
```

C++ class implementation

```c
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

```c
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