Wrapping C/C++ for Python using SWIG – Set 1

07 Jul, 2017
There is no doubt that C is faster than Python then how do Python library like Numpy perform huge number crunching job so fast and efficiently? Actually, libraries like Numpy are not completely written in Python instead, some parts of the library are written in C which provides performance boost. After writing code in C, we wrap them in Python code which acts like an interface for those C codes. We can then call C functions using Python syntax where actual processing is done in C behind the scene and the result is returned back as Python object. In this article, we will see how to create Python wrapper for our C program on Linux systems using a software called SWIG.
What is SWIG
In a nutshell, SWIG is a compiler that takes C/C++ declarations and creates a wrapper needed to access those declarations from other languages like Python, Tcl, Ruby etc.It normally required no changes in existing code and create an interface within a minute.
Reasons for creating wrapper
In many occasions we need wrappers, following are few of them –
Building interpreted interface for existing C programs.
Building high-performance C modules for scripting languages
It’s huge pain to test huge C programs, so we write wrappers in some scripting languages like Python, where it’s very easy to write test. etc
Installing SWIG
For downloading SWIG directly from apt repository type following commands –
sudo apt-get update
sudo apt-get install swig

Writing Wrapper using SWIG
Consider this piece of C code, having two functions and one global variable –
/* file : gfg.c */  #include <stdio.h>#include <math.h>  //our header file#include "gfg.h"#define ll long long  double myvar = 3.4;  // calculate factorialll int fact(ll int n){    if(n <= 1)        return 1;    else        return (n * fact(n-1));}  //find modint my_mod(int n, int m){  return(n % m);}
Here is our header file gfg.h –
long long int fact(long long int n);int my_mod(int n, int m);
First, we have to create a SWIG Interface file. This file contains ANSI C function prototypes and variable declaration. Here –
The %module directive specifies the name of the module we will use in Python.
%{ .. %} block provides a location to insert additional code such as C header files or additional C declaration into the generated wrapper code.
%include directive let us include additional files like header files.
/* file : gfg.i */  /* name of module to use*/%module gfg%{    /* Every thing in this file is being copied in      wrapper file. We include the C header file necessary     to compile the interface */    #include "gfg.h"      /* variable declaration*/    double myvar;%}  /* explicitly list functions and variables to be interfaced */double myvar;long long int fact(long long int n1);int my_mod(int m, int n);  /* or if we want to interface all functions then we can simply   include header file like this -    %include "gfg.h"*/
Now we will create wrapper code using the command like $ swig -target_language interface_file.i
$ swig -python gfg.i

After executing this command a wrapper code with name “gfg_wrap.c” is created. This files contains a bloated version of our original C code with various error handling code etc. Another file “gfg.py” is generated which is the module we will import in our python script.
After this, we have to generate position-independent code which will be used in shared library by compiling “gfg_wrap.c” and “gfg.c” using the following command –
$ gcc -c -fpic gfg_wrap.c gfg.c -I/use/include/python2.7

Replace python2.7 with your Python version. This will generate two object files“gfg_wrap.o” and “gfg.o”. In above command –
-fpic generate position-independent code (PIC) suitable for use in a shared library, if supported for the target machine. Such code accesses all constant addresses through a global offset table (GOT)
Note: If you get error something like “... ‘Python.h’ file not found” then following might be possible causes –
You might not have ‘Python.h’ file or
You are providing wrong location of ‘Python.h’ file to compiler
To get ‘Python.h’ You must install Python-dev using following command –
$ sudo apt-get install python-dev

To find the correct path of ‘Python.h’ execute following command –
$ python-config --cflags

This will output something like this –Now replace the path in compilation command with this one for python2.7 or change the version as python3.5 for Python 3.5.
Now, at last, we have to link generated objects files together to create a shared object which is analogous to dll files in windows. Use the following command, this will generate a “_gfg.so” shared object file –
$ gcc -shared gfg.o gfg_wrap.o -o _gfg.so

Now we are ready to test out python wrapper by importing it. Make sure you are in directory having this wrapper file.
>>> import gfg
>>> res = fact(5)
>>> res
120
>>> res = my_mod(5,2)
>>> res
1
>>> gfg.cvar.myvar
3.4

Here C variables are accessed as module.cvar.var_name.
Compiling and Linking using distutils
Instead of typing in commands and figuring out what compilation options are needed to compile files, we can automate this using distutils. Create a setup.py as below –
# File : setup.py  from distutils.core import setup, Extension#name of modulename  = "gfg"  #version of moduleversion = "1.0"  # specify the name of the extension and source files# required to compile thisext_modules = Extension(name='_gfg',sources=["gfg.i","gfg.c"])  setup(name=name,      version=version,      ext_modules=[ext_modules])
Now write following commands to compile and install module –
$ python setup.py build_ext --inplace

It should look something like this on terminal –
Possible Alternatives
Obviously, SWIG is not the only way for creating wrappers, one can consider following alternatives based on their requirements –
Manual Wrapping
pyrex
ctypes (Built in module)
SIP
In next article, we will see how to create wrapper for C++ code (OPP)
References
http://www.swig.org/Doc3.0/Introduction.html
This article is contributed by Atul Kumar. If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.
Python
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.