A simple python function to automate using the swig process for creating C modules for use inside Python.
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 | import commands
def swigit(modulename, Csources, Cheaders,
SwigExtra ="",
Libs = ['-lm'],
PythonIncludePath='/usr/local/include/python2.4/',
verbose=False):
"""
Creates a shared C module for inclusion in Python.
Arguments
modulename - name of module to create (no extension).
Cheaders - list of header files.
Csources - list of source files.
SwigExtra - additional swig declarations as a string.
Libs - list of extra libs to link.
PythonIncludePath - Python's include directory.
verbose - set to True for informative message printing.
In the current version, all header and source files are assumed to be
in the current directory.
"""
"""
1. Create the swig interface file modulename.i
"""
s = ""
s = "%module " + "%s\n" % modulename
s = s + "%{\n"
for header in Cheaders:
s = s + '#include "%s"\n' % header
s = s + "%}\n\n"
# Modify recipe to handle particular cases.
s = s + SwigExtra
for header in Cheaders:
s = s + "%%include %s \n" % header
if verbose:
print "Creating swig interface file with contents:\n", s
str2file(s, "%s.i" % modulename)
"""
2. Create the shared dll.
"""
s = "swig -python %s.i" % modulename
if verbose:
print "Processing interface file:"
print " ", s
status, output = commands.getstatusoutput(s)
if status != 0:
if verbose:
print output
return status
"""
3. Compile wrapper file.
"""
s = "gcc -Wall -I%s -fpic -c %s_wrap.c" % (PythonIncludePath, modulename)
status, output = commands.getstatusoutput(s)
s = "gcc -Wall -fpic -c "
for source in Csources:
s = s + " %s " % source
print "Compiling wrapper and source files to object files."
print " ", s
status, output = commands.getstatusoutput(s)
if status != 0:
if verbose:
print output
return status
"""
4. Create the shared module file.
"""
s = "gcc -Wall -O3 "
for lib in Libs:
s = s + " %s " % lib
s = s + " -shared %s_wrap.o" % modulename
for source in Csources:
s = s + " %s.o" % source.split(".")[0]
s = s + " -o _%s.so" % modulename
if verbose:
print "\nCreating module file."
print " ", s
status, output = commands.getstatusoutput(s)
if status != 0:
if verbose:
print output
return status
def str2file(s, filename):
"""
Dumps string to file.
"""
f = open(filename, "wt")
for lines in s.split("\n"):
print >> f, lines
f.close()
if __name__ == "__main__":
extra = """
%include "carrays.i"
%array_class(double, doubleArray)
%array_class(int, intArray)
"""
modulename = "mymodule"
if swigit(modulename, ["sphere.c"], ["sphere.h"], SwigExtra = extra, verbose=True) != 0:
print "There is an error in processing ", modulename
else:
import mymodule
x = mymodule.doubleArray(2)
x[0] = 2.0
x[1] = 1.0
print mymodule.sphere(2, x)
|
Simplifies creation of C shared modules for importing inside Python. Current version is for Linux platforms. To run the simple example, create the "sphere.c" file with contents
include <math.h>
include "sphere.h"
double sphere(int n, double x[]) { double s = 0.0; int i; for (i = 0; i < n; i++) { s += x[i] * x[i]; } return sqrt(s); }
The include file "sphere.h" contains
double sphere(int n, double x[]);
When the program runs, it outputs on my machine
[toto@localhost swig]$ python cswig.py Creating swig interface file with contents: %module mymodule %{
include "sphere.h"
%}
%include "carrays.i" %array_class(double, doubleArray) %array_class(int, intArray) %include sphere.h
Processing interface file: swig -python mymodule.i Compiling wrapper and source files to object files. gcc -Wall -fpic -c sphere.c
Creating module file. gcc -Wall -O3 -lm -shared mymodule_wrap.o sphere.o -o _mymodule.so 2.2360679775 [toto@localhost swig]$
The recipe is designed to handle simple cases of swigging. Modify the recipe for more complex requirements.
Example broken. The example is corrupted. What is in sphere.h?
Fixed the recipe's example discussion.