swig

swig is not a Python module. Instead it interfaces C/C++ to other languages. We are obviously interested in extending Python by some C code. Below you find a complete example including a function calculating the factorial and two functions mirroring a string.

The interface:

 
/* File : example.i */

%module example
%include <cstring.i>
%cstring_bounded_output(char* outstr, 1024);
%{
/* Put headers and other declarations here */
extern int  fact(int);
extern char *mirroredText( char *, int *OUTPUT);
extern int   mirroredTextV2( char *, char *outstr);
%}

extern int  fact(int);
extern char *mirroredText( char *, int *OUTPUT);
extern int   mirroredTextV2( char *, char *outstr);

The c-code:

 
/* File : example.c */

#include <string.h>
#include <stdio.h> 

/* Compute factorial of n */
int fact(int n) {
  if (n <= 1)
    return 1;
  else
    return n*fact(n-1);
}

char *mirroredText( char *inString, int *argout)
 {
   static   char buffer[ 80];
   strcpy( buffer, inString);
   strcat( buffer, "_mirrored");
   *argout = strlen( buffer);
   return buffer;
 }


int mirroredTextV2( char *inString, char *argout) {
  strcpy( argout, inString); 
  strcat( argout, "_mirroredV2"); 
  return strlen( argout); 
}

Two scripts to make it for Python2 and Python3.

Do2.sh:

 
#!/usr/bin/env bash 

echo "swig -python example.i"
swig -python example.i
echo "gcc -c -fpic example.c"
gcc -c -fpic example.c example_wrap.c -I/usr/include/python2.7
echo "gcc -shared -o _example.so"
gcc -shared example.o example_wrap.o -o _example.so
echo "executing 'python xmplTest.py'" 
python xmplTest.py

Do3.sh:

#!/usr/bin/env bash 

echo "swig -python example.i"
swig -python example.i
echo "gcc -c -fpic example.c"
gcc -c -fpic example.c example_wrap.c -I/usr/include/python3.5
echo "gcc -shared -o _example.so"
gcc -shared example.o example_wrap.o -o _example.so

echo "executing 'python3 xmplTest.py'" 
python3 xmplTest.py

The Python script that tests the code:

 
#!/usr/bin/env python
"""
this script performs tests for example.c

Depending on whether the .so has been made
with Do2.sh or Do3.sh this script is launched by: 

  python xmplTest.py
or
  python3 xmplTest.py

"""
import example
import sys

def main():
    print( "\n--- xmplTest.py")
    print( "Python version: %s" % repr(sys.version))
    i = 4
    ret = example.fact( i)
    print( "fact(%d) = %d" % (i, ret))
    if ret == 24: 
        print( "OK")
    else: 
        print( "bad result: %s" % repr( ret))

    t = "hello"
    ret = example.mirroredText( t)
    print( "mirroredText( '%s'):   %s" % ( t, repr( ret)))
    if ret[0] == 'hello_mirrored' and ret[1] == 14:
        print( "OK")
    else: 
        print( "bad result: %s" % repr( ret))

    ret = example.mirroredTextV2( t)
    print( "mirroredTextV2( '%s'): %s" % (t, repr( ret)))
    if ret[1] == 'hello_mirroredV2' and ret[0] == 16:
        print( "OK")
    else: 
        print( "bad result: %s" % repr( ret))

if __name__ == '__main__':
    main()