SWIG and Python: Calling C functions from python through SWIG in Solaris

Sunday, July 12, 2009


I was a fan of SWIG some time back when I was developed new python APIs for our test automation framework through that tool, but when I recently revisited the same topic, I was caught unaware as it was not a trivial task like compiling a C or python code and it will do the magic for you, it involved a customized Makefile at that time which I didn't recollect after a long time, fortunately after some experimentation, I was able to come up with a quick documentation on the steps you need to do to make Python-SWIG work on Solaris 10 and above (the platform I in which tested the code).

In this example, we will have a C file with two math functions add and sub, which gets two numbers from the user and outputs the result of addition and subtraction operations respectively, I was also interested in how direct C I/O would work from python, i.e I want the numbers to be input from python shell to C and get the results back and print them, we will see the series of steps required to do the same through SWIG.

1. Setting Paths
2. Installing SWIG
3. The C Code
4. The SWIG Interface file
5. Compiling the stuff
6. Running the python module

1. Setting Paths

This is a simple, yet a crucial step which I want to list first, time and again when I execute the commands required to compile stuff through SWIG, the default path for different utilities were not set, therefore make sure that you have the following locations included in your PATH environment variable (though the /usr/local/bin will make sense only after you install SWIG).

export PATH=$PATH:/usr/ccs/bin:/usr/sfw/bin:/usr/local/bin:

All I would say is is ld, make utilities are in /usr/ccs/bin, gcc (the compiler I used) would be in /usr/sfw/bin and swig (would be) installed in /usr/local/bin.

Now we are all set to install SWIG.

2. Installing SWIG

Feel free to skip this step if you already installed one, else you can follow the SWIG web-page for detailed instructions or a short step-by-step summary mentioned below.

1. Download swig 1.3.21 (the one I used for compiling this code) here.

2. gzip -d swig-1.3.21.tar.gz

3. tar -xf swig-1.3.21.tar

4. cd SWIG-1.3.21 (the un-tared directory)

5. ./configure

6. make

7. make install

I am very sure that by the time you read this line, you should have successfully installed SWIG (in /usr/local/bin), for installing the latest version of SWIG follow the appropriate instructions from the SWIG web-page.

3. The C Code

Again, another trivial section, I am listing the C Code which is used to do math operations add and sub, which will add and subtract two numbers input by the user.

Listing 1: math_io.c

1.  // math_io.c
2.  // A Sample Addition Program in C with I/O to be called from python
3.  // Author: S.Prasanna 
4.
5.  #include
6.
7.  int a, b;
8.
9.  // Add two numbers and return result
10. int add() {
11.  printf("Addition: Enter two numbers:");
12.  scanf("%d", &a);
13.  scanf("%d", &b);
14.  return a + b;
15. }
16.
17. // Subtract two numbers and return result
18. int sub() {
19.         printf("Subtraction: Enter two numbers:");
20.         scanf("%d", &a);
21.         scanf("%d", &b);
22.         return a - b;
23. }
I hope the above code doesn't deserve an explanation, does it?

4. The SWIG Interface file


Till now you had an easy ride, now the real work starts, you need to have a SWIG interface file for the C code you wrote above through which the python module will be generated which will call the C functions, our SWIG interface definition is quite simple, right now its good enough if you understand that we are declaring the functions add and sub in the SWIG interface file to be accessed from python, for more details on how SWIG works, do look at this paper on SWIG.

Listing 2: math_io.i

1.  /* math_io.i */
2.  /* SWIG interface file for math_io.c */
3.  /* Author: S.Prasanna */
4.
5.  %module math_io
6.  %{
7.   extern int add();
8.   extern int sub();
9.  %}
10.
11. extern int add();
12. extern int sub();
Explanation:

In the above code, the SWIG interface file defines a module math_io (line 5) to be accessed from python which will call the functions add and sub (lines 7 - 8 and 11 - 12).

5. Compiling the stuff


I am assuming that you have math_io.c (C source code) and math_io.i (SWIG interface file) in a directory (say /swig-example) with the PATH set as mentioned above, to compile the code, follow the below steps. (the commands are indicated in bold italics)

bash-3.00# pwd
/swig_example
bash-3.00# ls
math_io.c  math_io.i
bash-3.00# swig -python math_io.i
bash-3.00# ls
math_io.c       math_io.i       math_io.py      math_io_wrap.c
After the first command (swig -python math_io.i), we see a python file (math_io.py) and a C wrapper file (math_io_wrap.c) generated by SWIG.
bash-3.00# gcc -c -I/usr/sfw/include/python2.3/ math_io.c math_io_wrap.c
bash-3.00# ls
math_io.c       math_io.i       math_io.o       math_io.py      math_io_wrap.c  math_io_wrap.o
bash-3.00#
Now we compile math_io.c and the SWIG generated wrapper C source file math_io_wrapper.c which results in two object files math_io.o and math_io_wrap.o.

Note: I used python 2.3 to compile the above code, you need to point to the location of Python.h and other dependencies based on the python interpreter version installed in your system (change the above directory after the -I option supplied to gcc accordingly).

Finally generate the shared library module to access the C functions from python.
bash-3.00# ld -G math_io.o math_io_wrap.o -o _math_io.so
bash-3.00# ls 
_math_io.so     math_io.c       math_io.i       math_io.o       math_io.py      math_io_wrap.c  math_io_wrap.o
Note that the shared library is named _math_io.so (the naming conventions are important to access the right shared library module from python).

6. Running the python module

The easiest part after doing all the hard work, to access the C functions from python.

bash-3.00# python
Python 2.3.3 (#1, Nov 22 2005, 01:28:00) [C] on sunos5
Type "help", "copyright", "credits" or "license" for more information.
>>> import math_io
>>> dir(math_io)
['__builtins__', '__doc__', '__file__', '__name__', '_math_io', '_newclass', '_object', '_swig_getattr', '_swig_setattr', 'add', 'sub']
>>> math_io.add()
Addition: Enter two numbers:6
2
8
>>> >>> math_io.sub()
Subtraction: Enter two numbers:6
2
4
>>> >>> ^D
bash-3.00#
Hope you went through this exercise without much trouble, as I mentioned earlier I tested the above steps on Solaris 10, but should work with any Solaris installation.

3 comments:

Anonymous said...

Thanks for quick tutorial. It helped me get an idea of what SWIG is and how it interfaces with C libraries.

rajashree said...

Hi,
I was impressed with the details here, can you please help me answer below query -

I would like to know hot to pass address reference to ‘c’ function through python. I am using swig for ‘c’ anf python interfacing







Interface file : stud.i

***************************************************



%module stud



%header%{

#include "stud.h"

%}



%include "stud.h"



%array_functions(char *,charp );



%inline %{

extern int parse1(char *,char *,char **);

%}



%inline %{

int print_args(char **argv) {

int i = 0;

for(i=0;i<=180;i++) {

printf("argv[%d] = %c\n", i,*(argv[i]));

i++;

}

return i;

}

%}



**********************************************************



Stud.c

======================================

#include string.h

#include stdio.h

/*the angular braces are removed as here as they were causing issues in posting*/

#include "stud.h"



int parse1(char *s, char *p,char **t)

{

strcat(p,s);

*t=&p[0];

}



**********************************************************

Stud.h

===================================



int parse1(char *,char *,char **);



**************************************************

>>> from stud import *

>>> a='rajashree'

>>> c='thoratf'

>>> d=new_charp(1000)

>>> parse1(a,c,d)

2300188

>>> d

Swig Object of type 'char **' at 0x28aca0




Now I want read value of d in python… How do I do it.

Any type of help is appreciated.

Thanks,
Rajashree.
rthorat@starentnetworks.com

giridhar said...

Hi i'm not able to install SWIG in cygwin. When i go for 'make install' command then i'm getting error has


make: /cygdrive/c/SWIG-1.3.24/Tools/config/install-sh: command not found

make: *** [install-main] error 127

Pls give me solution for how to fix it.
Thank u


Copyright © 2016 Prasanna Seshadri, www.prasannatech.net, All Rights Reserved.
No part of the content or this site may be reproduced without prior written permission of the author.