First off, we need to provide a SWIG interface file (Multiply.i) to tell SWIG about our library. SWIG is very powerful because it is able to obtain a lot of information from the library header file, for example, it can work out that Data_t is typedef'd to a double. However we do need to assist SWIG and tell it that we are going to be handling arrays of floating point data.
To do this we include the SWIG interface file "carrays.i" and tell SWIG we want to use the array_class interface. The complete interface file is shown here :
%array_class(double, doubleArray); /* Include support for "double *" functions */
%array_class(long, longArray); /* Include support for "long *" functions */
With this file we can now create the importable Python module that contains the functions we want to access. This is essentially a two stage process :
Compile the library into a Python importable module
Here is a complete batch file for creating a Python wrapper for accessing the library. Note that we are calling the new DLL (Multiply_wrap.dll) to differentiate it from Multiply.dll created in the earlier blog. Note that Python expects the file to be called Multiply_wrap.pyd so we will also rename it.
Please refer to the remarks for additional comments.
rem Delete the wrapper c file so that if it is not regenerated using swig then the compile will fail
rem this is helpful for development because if the you don't delete the old file then the compiler
rem will just process that, which might not be what you want !
c:\swig\swig -python -includeall Multiply_wrap.i
cl -Od -MD -DNDEBUG -DWIN32 -IC:\Anaconda\envs\py33\include -D_CONSOLE -DSTATIC_LIB=1 -DNO_STRICT Multiply_wrap_wrap.c /link user32.lib Multiply.lib C:\Anaconda\envs\py33\libs\python33.lib /DLL /out:Multiply_wrap.dll /NODEFAULTLIB:LIBCMT
rem The Python module should have extension .pyd
rem so we will delete the old one and rename the newly created dll
if exist _Multiply_wrap.pyd del /Q _Multiply_wrap.pyd
ren Multiply_wrap.dll _Multiply_wrap.pyd
Finally, we need to write a test script to access the C coded function.
This function includes some additional functionality that is not strictly necessary but this is to show some additional useful techniques such as :
Printing the attributes of the library
Converting Python lists to C arrays and back again
Accessing the values of C #define constants from Python
Here is the complete Test.py script :
import multiply_wrap # Note the module name must be lower case !
print ('Library attributes :') # Print the attributes of the library
for a in dir(Multiply_wrap):
a = [1.2, 3.4, 5.6, 7.8, 9.0]
b = [1000.1, 100.2, 1000.3, 1000.4, 1000.5] # Destination array to put results into
print ('PI = ') # Print a constant defined in C
p_a = Multiply_wrap.doubleArray (5)
p_b = Multiply_wrap.doubleArray (5)
for index, item in enumerate(a): # Copy data to array p_a
p_a[index] = item
print ('a = ') # Print contents of a
for i in range(0,5):
Multiply_wrap.VectorScalarMultiply (p_a, Multiply_wrap.TWO_PI, p_b, 5)
for i in range(0,5): # Copy data to b
b[i] = p_b[i]
print ('Scaled a = ')
Finally, if you have found this solution useful then please do hit the Google (+1) button so that others may be able to find it as well.