Swig to wrap C Code

Prerequisite: Using C codes in Python, Wrapping C/C++ for Python using SWIG
Suppose we have given a C code and it needs to be accessed as a C extension module. So, for the given task – Swig Wrapper Generator is used.
Swig operates by parsing C header files and automatically creating extension code. C-header file is needed first, to use Swig. Give an example of C-header file in the code below.
Code #1 : work.h
// work.h   # include <math.h>   extern int gcd(int, int); extern int divide(int a, int b, int * remainder); extern double avg(double * a, int n);   typedef struct Point {     double x, y; } Point;   extern double distance(Point * p1, Point * p2);  | 
 
After having the header file, the next step is to write a Swig “interface” file. By convention, these files have a .i suffix and might look similar to the following.
Code #2 : work.i
// work.i - Swig interface % module work % { # include "work.h"     % } // Customizations % extend Point {     // Constructor for Point objects      Point(double x, double y)     {         Point * p = (Point *) malloc(sizeof(Point));         p->x = x;         p->y = y;         return p;     }; };  | 
 
Code #3 : Mapping
// Map int * remainder as an output argument %include typemaps.i  %apply int * OUTPUT { int * remainder };    // Map the argument pattern (double * a, int n) to arrays  %typemap(in) (double * a, int n)(Py_buffer view) {     view.obj = NULL;     if (PyObject_GetBuffer($input, &view,                             PyBUF_ANY_CONTIGUOUS | PyBUF_FORMAT) == -1)     {         SWIG_fail;     }     if (strcmp(view.format, "d") != 0)     {         PyErr_SetString(PyExc_TypeError,                          "Expected an array of doubles");         SWIG_fail;     }     $1 = (double *) view.buf;     $2 = view.len / sizeof(double); }    % typemap(freearg) (double * a, int n) {     if (view$argnum.obj)     {         PyBuffer_Release(&view$argnum);     } }  | 
 
Once the interface file is ready, Swig is invoked as a command-line tool
Code #4 :
bash % swig -python -py3 work.i bash %  | 
 
The output of swig is two files – work_wrap.c and work.py. work.py file is what users import and the work_wrap.c file is C code that needs to be compiled into a supporting module called _work. It is performed using the same techniques as for normal extension modules. For example, creating a setup.py file as shown in the code below –
Code #5 :
# setup.py from distutils.core import setup, Extension setup(name='sample',        py_modules=['sample.py'],       ext_modules=[ Extension(               '_sample', ['sample_wrap.c'],                include_dirs = [],                define_macros = [],               undef_macros = [],               library_dirs = [],               libraries = ['sample']               ) ] )  | 
 
Code #6 : Compile and test, run python3 on the setup.py
bash % python3 setup.py build_ext --inplace running build_ext building '_sample' extension   gcc -fno-strict-aliasing -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -I/usr/local/include/python3.3m -c work_wrap.c -o build/temp.macosx-10.6-x86_64-3.3/work_wrap.o   work_wrap.c: In function ‘SWIG_InitializeModule’:   work_wrap.c:3589: warning: statement with no effect   gcc -bundle -undefined dynamic_lookup build/temp.macosx-10.6-x86_64-3.3/work.o   build/temp.macosx-10.6-x86_64-3.3/work_wrap.o -o _work.so -lwork bash %  | 
 
After performing all the tasks, we can use the C extension module in a very easy way. 
Code #7 :
import work print ("GCD : ", work.gcd(12,8))   print ("\nDivision : ", work.divide(42,8))   pt1 = work.Point(2,3) pt2 = work.Point(4,5)   print ("\nDistance between pt1 and pt2 : ",         work.distance(pt1,pt2))     print ("\nx co-ordinate of pt1 : ", pt1.x) print ("\ny co-ordinate of pt1 : ", pt1.x)     import array ar = array.array('d',[2, 4, 6]) print ("\nAverage : ", work.avg(arr))  | 
Output :
GCD : 4 Divide : [5, 2] Distance between pt1 and pt2 : 2.8284271247461903 Distance between pt1 and pt2 : 2.0 Distance between pt1 and pt2 : 3.0 Average : 4.0
				
					


