Extending Python with ctypes
ctypes is a foreign function library for Python. It provides C compatible data types, and allows calling functions in DLLs or shared libraries. It can be used to wrap these libraries in pure Python.
This tutorial assumes a Debian based GNU/Linux distribution. You may have to install build-essential.
Writing your shared library
We’ll start by creating our shared library. Type the following into your favorite text editor and save the file as testlib.c:
const char *say_hello() {
return "Hello, World\n";
}
Compile and link thusly:
gcc -g -c -Wall testlib.c
gcc -shared -Wl,-soname,libtestlib.so.1 -o libtestlib.so.1 testlib.o -lc
If you didn’t encounter any errors, you should be left with a file named libtestlib.so.1 in the same directory as your source.
Next, you’ll want to make sure that ldconfig can load your library. The easiest way to do this is to create a file named testlib.conf in /etc/ld.so.conf.d/ containing the path where your shared library can be found.
Run the following command to verify that ldconfig can see your library:
ldconfig -v | grep testlib
With luck you should see something like this:
/home/kyle/src/ctypes_test/testlib:
libtestlib.so.1 -> libtestlib.so.1
Using your shared library with ctypes
Fire up the interactive interpreter and type the following:
>>> from ctypes import cdll, c_char_p
>>> testlib = cdll.LoadLibrary('libtestlib.so.1')
>>> testlib.say_hello.restype = c_char_p
>>> testlib.say_hello()
Hello, World
>>>
You should, of course, see Hello, World displayed as the return value.
A little abstraction never hurts
Here’s a quick example of making your ctypes bindings a little easier to use:
from ctypes import cdll, c_char_p
class TestLib:
def __init__(self):
self.lib = cdll.LoadLibrary("libtestlib.so.1")
self.lib.say_hello.restype = c_char_p
def say_hello(self):
return self.lib.say_hello()
testlib = TestLib()
print testlib.say_hello()