File: swig_info

package info (click to toggle)
lfc-postgres 1.7.4.7-1
  • links: PTS, VCS
  • area: main
  • in suites: squeeze
  • size: 13,676 kB
  • ctags: 10,779
  • sloc: ansic: 146,136; sh: 13,176; perl: 11,142; python: 5,529; cpp: 5,113; sql: 1,790; makefile: 861; fortran: 113
file content (248 lines) | stat: -rw-r--r-- 10,833 bytes parent folder | download | duplicates (8)
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
237
238
239
240
241
242
243
244
245
246
247
248
INTRODUCTION
============
SWIG can be used to create a Python (or some other languages) API based on an existing
C/C++ API. SWIG wrappes the C/C++ functions with functions in the target language, and
mappes C/C++ data (including structs and objects) to data structures of the target 
language.

In what follows we will refer only to python, although other target languages
may be consider in a similar way.

Basically, the way to utilize SWIG to create a python wrapper API on a given C/C++ API
(defined by some .h files) is the following:

 1 - Create a SWIG interface file (.i file)

 2 - Run:
        swig -I<C_API_include_dirs> -python <myFile>.i
        
     This creates a python file (myFile.py) and a C file (myFile_wrap.c), which contain
     the code that python needs to interface with the C API. In some cases, inspection
     of the C file may be useful to find out problems in the wrapping.

 3 - Compile both the original C files and the newly created C wrapper:
        gcc -g -c -I<C_API_include_dirs> -fPIC <myFile>.c
        gcc -g -c -I<C_API_include_dirs> -fPIC  -I</usr/include/python2.2> <myFile_wrap>.c
        gcc -g -shared <myFile>.o <myFile_wrap>.o -o _<myFile>.so <C_API_linker_directives>

     This will generate a _<myFile>.so file, which is a dynamic library used by the python
     module <myFile>.py. 

 4 - Run python in a way that the module and dynamic library files are accessible (e.g. in 
     the same dir as these), import the created module, and use the functions.

     >>> import myName
     >>> x = myName.myFunction(12)
    
     The structs, objects and unkown pointers (almost all) in C/C++ are wrapped with python
     objects. To use a struct (e.g. struct 2ints, with 2 fields A and B of type int):

     >>> x = myName.2ints()
     >>> x.A = 3
     >>> x.b = 0
     >>> print x.A
     3
     >>>

     The char* vars are mapped as python strings.


THE SWIG INTERFACE FILE
=======================
Of the whole wrapping process, the only non-mechanical part may be the creation of 
the interface file (.i). Any non-trivial conversion will be specified there.

The format of the file is:
-----------------------------------------------
/* Define the module name*/
%module <myName>

/* Include the typemaps functionality if required*/
%include "typemaps.i"

/* Include the C API headers, to be able to wrap the functions */
%{
#include <some_file.h>
#include "some_other_file.h"
%}

/* User-defined typemaps */

/*
   C/C++ declaration of all functions to be converted.
   Normally this is a series of %include for the .h files of the C API.
*/
------------------------------------------------

If no typemaps are used (see below), then the file is trivial.


TYPEMAPS
========
For trivial cases, SWIG will do the wrapping of the functions automatically, but in
some cases, the default conversion of the input or output arguments may not be
adequate. For those cases, the user needs to replace the default behaviour by 
defining some typemaps.

The typemaps can be defined for different uses; e.g.: adapting the conversion of the
input arguments typemap(in), of the output arguments typemap(out) or of the arguments
that are used as input/output (typemap(argout)). And they are defined for certain
arguments type (and maybe name). The functions defined after the typemaps that
match the typemap arguments type (and the name, if included) use this user-defined
conversion, instead of the default.

The %apply directive is used to extend the typemap definition to other argument names
(normally to modify a general typemap to a concrete C API case, using the concrete
names of this C API, or just eliminating these names, so that it applies to every function
with those arguments type).

The %clear directive is used to finish the application area of a typemap (normally used
to avoid that other functions defined below apply a typemap that was not intended for them).

A secure way to defined typemaps, not to let them affect functions they are not intended 
for is to limit their effect to the definition of the specific function we want them for.
-----------------------------------------
%typemap(in) (char* INPUT_1, int INPUT_2){
  /* blah blah */
}

%apply(char* INPUT_1, int INPUT_2) {(char* name, int value)};

// C definition
int setAttr(char* name, int value);

%clear (char* name, int value);


// Other definitions (if the prev one is repeated (e.g. in an %include), this 2nd one is ignored)
-----------------------------------------

When is a typemap necessary? Whenever the default python conversion for an argument is
not OK. This may be the case when user-defined C++ objects are used, or, in C, when
pointers are passed around in functions, because they cannot be dereference.

Usually, whenever a function requires an array of structs, passed as a pointer to that struct
and a length, a typemap is needed. Also, if a pointer is passed to be filled by the application
and returned to the caller (input/output argument) typemap is needed, because the caller
will not be able to dereference the value.

There are several constructs available for the programmer, mainly:
 PyObject* : Pointer to any object in python
 Py_None : represents the none in python
 PyObject* PyInt_AsLong()... : Functions to map basic C types into python objects
 PyObject* PyList_New(), PyList_SetItem()... : Functions to create and manage a python list
 General-use pointer converters: see later.


Input typemap
*************
%typemap(in, numinput=X) (my_struct * INPUT_1, int INPUT_2) { ... }

Whatever we put in the typemap will get executed before the actual call to the C function.
The typemap indicates that the python wrapper will accept X arguments (0 or 1) instead of
the ones defined here (INPUT_1 and INPUT_2). We may apply different typemaps to
different arguments of the same function.

Usual use case is that the python wrapper receives a list (X=1) and we extract from it
the length and the struct array and pass those to the C function. For that, we have to
give value to $1 and $2 ($3...), which will go in the place of INPUT_1 and INPUT_2. What
we get from the python wrapper is accessible via the variable $input.

We might also have no input from the wrapper (X=0), but still we have to pass something
to the C function, so that it works. If it is a pointer, to be set, something like the
following may be used:
   int tmp_int;
   $1 = &tmp_int;

The tmp_int var is local to the input typemap, so it will not be available when the C
function call arrives. If the C function just sets $1 to point somewhere else, this is
not important, but if that memory is to be used, then it must be put on the heap (with
new), so that it stays there. In that case, of course, somebody has to release it 
afterwards, either with a %freearg typemap, or by some other means.


Freearg typemap
***************
It will get executed after the C function and after output and argout typemaps code. 
It should contain code to free the resources allocated in the heap in the input 
typemap (only to use if these resources won't be needed anymore after the wrapper
function returns!).


Output typemap
**************
%typemap(out) my_struct *OUTPUT_1 { ... }

Like in the input typemap, whatever code we include here, gets executed after the C function
is called. Here we have to set $result (which is of type PyObject *) to what we want to
return to the wrapper python function. We count with $1 as the returned value of the C
function (OUTPUT_1).


Argout typemap
**************
%typemap(argout) (my_struct * ARGOUT_1, int ARGOUT_2) { ... }

Also executed after the output typemap. It is used to set the $result, based on the previous
value of $result (possibly set by the output typemap) and the returned values of the
input/output arguments $1, $2... (ARGOUT_1 and ARGOUT_2).


GENERAL CASE POINTER CONVERTERS
===============================
Functions like PyInt_AsLong() can be used to get a python number (always returned as
PyObject *) from a given C long. Structs and objects in C/C++ that are also mapped into
python objects can also be converted within a typemap. However, there is not a different
function for each case, only two general functions for one way or the opposite. These are 
fundamental functions.

To convert from python object to C:
***********************************
SWIG_ConvertPtr(PyObject* obj, (void**) p, $descriptor(my_struct *), flags);

This moves the given pointer p, to point to a newly allocated struct representing
the python object obj. $descriptor() is a function that returns the internal swig type
mapping for the given C/C++ type.

Notice that p does not need memory allocated previously, because it is moved to a new area.

The argument flags can be set to the bitwise OR of SWIG_POINTER_EXCEPTION (raise an
exception on type error) and, maybe, SWIG_POINTER_DISOWN (in this case, we steal the ownership
from the python object, so we should delete it ourselves... not usually recommended).


To convert from C to a python object:
*************************************
PyObject * obj = SWIG_NewPointerObj(my_struct* p, $descriptor(my_struct *), PYTHON_OWNED);

This builds acess methods for a python object reading the underlying C struct pointed by p.

Notice that there is no new memory allocated, the python object data is still the same C
struct, so we cannot modify or release it while the python object is to be used!

PYTHON_OWNED is either 0 (we keep ownership of the struct, so we must release it ourselves
(with free...)) or 1 (python gets ownership of the struct, so it will be released whenever
the object is deleted).

Normally, the python object will be used after the wrapper function ends (because normally
it is part of the return value of the function), so we cannot release the struct, so we 
should set PYTHON_OWNED to 1, not to leave a memory leak.

However, there may be situations where this is not the case. E.g.: If this struct was set
by somebody else and a future function will release it (like a closedir()). Or, e.g., if
we have set an array of structs with a single call to malloc (and one single struct*), but
we are building a list of python objects. In this case, only the first object must be set
as owner of the struct (PYTHON_OWNED=1), and the other must have PYTHON_OWNED=0. This is
because the first free() of the first object (in its destructor code) will already release
all the memory originally set for the structs array, and if the rest of objects tried the
same (because they owned the object as well), they would cause a seg fault, trying to free
something already released.



MORE INFORMATION
================
http://www.swig.org
And in particular: http://www.swig.org/Doc1.3/Contents.html
Typemaps chapter: http://www.swig.org/Doc1.3/Typemaps.html
Python chapter: http://www.swig.org/Doc1.3/Python.html