summaryrefslogtreecommitdiffstats
path: root/md/writeup/wraping_c_plus_plus_exceptions_templates_and_classes_in_c.md
blob: 0f43f21e60fd858edb746ec04e93c412c6211493 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
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