Python always got a good relation with the C language, through its syntax affinity or with its own API integrated with C.
Presentation's goal is to describe and compare several ways of doing bindings in C/C++ for Python which allow to augment Python features through speed improvements or giving access to a large ecosystem of C/C++ (or other) libs.
Following is presented : Python C API, ctypes, SWIG, Cython speaking about qualities and weak points.
2. Python C API PythonBrasil[5] Caxias do Sul, RS - Brazil
3. 3 Python C API : philosophy Everything is a PyObject* Public symbols with Py prefix Private symbols with _Py prefix Objects are stored in memory heap It’s you job to count the references Py_INCREF & Py_DECREF Yeah, that’s sucks! There are functions to convert C data types to Python C data types and back PyArg_ParseTuple() Py_BuildValue()
4. Python C API A wrapper around two readline functions: readline - return a malloced string add_history - add a (const) string to the history char *readline(const char *); intadd_history(const char *);
5. Python C API readline() #include <Python.h> #include <readline/readline.h> PyObject * fn_readline(PyObject *self, PyObject *args) { char *prompt; char *line; PyObject *o; if (!PyArg_ParseTuple(args, "s", &prompt)) return NULL; line = readline(prompt); o = Py_BuildValue("s", line); free(line); return o; }
6. Python C API add_history() PyObject * fn_add_history(PyObject *self, PyObject *args) { char *line; int status; PyObject *o; if (!PyArg_ParseTuple(args, "s", &line)) return NULL; status = add_history(line); o = Py_BuildValue("i", status); return o; } And if I want to return None? Py_INCREF(Py_None); return Py_None;
8. Python C API Compiling... $ gcc -dynamiclib -I/usr/include/python2.5 -lpython -lreadline mod_readline.c -o readline.so Or you can use distutils / setup.py
9. Python C API The goods Strong C/C++ and Python integration The best performance possible Full Python data types support The bads It’s hard work, only good for masochists You’re supposed to be good in C Reference counts nightmare
12. SWIG : philosophy Everything is defined in the interface file Module name Literal #include or source code Define What symbols to export The swig compiler translates the interface file into C source code
14. SWIG Compiling... $ swig -python readline.i $ gcc -creadline_wrap.c -I/usr/include/python2.5 $ gcc -dynamiclibreadline_wrap.o -lpython -lreadline -o _readline.so Or you can use distutils / setup.py
15. SWIG The goods Full bindings process automatization Strong C++ support (class, template, exception) Not only for Python! Support for Perl, Ruby and others It’s mature (since 1995) The bads The C file created is not for human consum Callbacks and double references are not easy
18. Ctypes : philosophy Ctypes is a dlopen-like for Python The basic steps : Obtain a handle of a library Use this handle to access library’s functions from ctypes import cdll libc_h = cdll.LoadLibrary(“libc.so.6”) libc_h.mkdir(“python-mkdir-test”)
19.
20. Ctypes What if I want specific C types? c_int, c_long, c_char, c_short, c_ulong, … i = c_int(10) print i.value() 10
21. Ctypes Functions return values? By default, assumed to be int from ctypes import cdll, c_char_p lr = cdll.LoadLibrary("libreadline.dylib") while True: line = lr.readline(“C:>") c_line = c_char_p(line) if not c_line.value: break
22. Ctypes Return value as input for another C function? from ctypes import cdll, c_char_p lr = cdll.LoadLibrary("libreadline.dylib") while True: line = lr.readline(“C:>") c_line = c_char_p(line) if not c_line.value: break lr.add_history(c_line.value) # or lr.add_history(c_line) # or lr.add_history(line)
23. Ctypes Is there a way to simplify a bit? from ctypes import cdll, c_char_p lr = cdll.LoadLibrary("libreadline.dylib") lr.readline.restype = c_char_p while True: line = lr.readline("c:>") if not line: break lr.add_history(line) You can define types for arguments too with .argtypes!
24. Ctypes Possible to access structures returned by C functions Possible to define arrays … but with a fixed length! Possible to create callback written in Python called by C lib. On windows, check the number of parameters passed to a function. Part of Python 2.5
27. Cython : philosophy Cython is an extension of Python language Three simple steps : Write “python” Compile the module it with C compiler Import the package in your python code
28. Cython Compiling a module => setuptools print “hello world!” setup.py from distutils.core import setup from distutils.extension import Extension from Cython.Distutils import build_ext setup( cmdclass = {'build_ext': build_ext}, ext_modules = [Extension(”hello", [”hello.pyx"])] )
29. Cython cdef extern from "readline/readline.h": char* readline(char*) intadd_history(char*) def readline_loop(): while True: line = readline("c:>”) if not line: break add_history(line)
30. Cython setup.py from distutils.core import setup from distutils.extension import Extension from Cython.Distutils import build_ext setup( cmdclass = {'build_ext': build_ext}, ext_modules = [Extension(‘readlineloop’, [‘readline-loop.pyx’], libraries = [‘readline’])] )