python bindings overview

35
PYTHON BINDINGS OVERVIEW Rudá Moura : [email protected] Sébastien Tandel : [email protected]

Upload: sebastien-tandel

Post on 19-May-2015

10.424 views

Category:

Technology


6 download

DESCRIPTION

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.

TRANSCRIPT

Page 1: Python Bindings Overview

PYTHON BINDINGS OVERVIEWRudá Moura : [email protected]

Sébastien Tandel : [email protected]

Page 2: Python Bindings Overview

PYTHON C APIPythonBrasil[5]

Caxias do Sul, RS - Brazil

Page 3: Python Bindings Overview

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()

Page 4: Python Bindings Overview

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 *); int add_history(const char *);

Page 5: Python Bindings Overview

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;}

Page 6: Python Bindings Overview

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;

Page 7: Python Bindings Overview

PYTHON C API

Registering functions and modules

static PyMethodDefmethods[] = { {"readline", fn_readline, METH_VARARGS, NULL}, {"add_history", fn_add_history, METH_VARARGS, NULL}, {NULL, NULL, 0, NULL}};

PyMODINIT_FUNCinitreadline(void){ (void) Py_InitModule("readline", methods);}

Page 8: Python Bindings Overview

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

Page 9: Python Bindings Overview

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

Page 10: Python Bindings Overview

PYTHON C API : SUMMARY

Learning Curve

Pythonic

C

C++

Others languages

Exceptions handling

Page 11: Python Bindings Overview

SWIGSimplified Wrapper and Interface Generator

Page 12: Python Bindings Overview

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

Page 13: Python Bindings Overview

SWIG

The interface file

// readline.i

%module readline

%{#include <readline/readline.h>%}

char *readline(const char *);int add_history(const char *);

Page 14: Python Bindings Overview

SWIG

Compiling...

$ swig -python readline.i $ gcc -c readline_wrap.c -I/usr/include/python2.5 $ gcc -dynamiclib readline_wrap.o -lpython -lreadline -o _readline.so

Or you can use distutils / setup.py

Page 15: Python Bindings Overview

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

Page 16: Python Bindings Overview

SWIG : SUMMARY

Learning Curve

Pythonic

C

C++

Others languages

Exceptions handling

Page 17: Python Bindings Overview

CTYPES

Page 18: Python Bindings Overview

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 cdlllibc_h = cdll.LoadLibrary(“libc.so.6”)libc_h.mkdir(“python-mkdir-test”)

Page 19: Python Bindings Overview

CTYPES

OK, it’s a dlopen-like, and?

libc_h.mkdir(“python-mkdir-test”)

It’s a Python string!

Transparent conversion for these types : None, integers, long, byte strings and unicode

strings

Page 20: Python Bindings Overview

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

Page 21: Python Bindings Overview

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

Page 22: Python Bindings Overview

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)

Page 23: Python Bindings Overview

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 !

Page 24: Python Bindings Overview

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

Page 25: Python Bindings Overview

CTYPES : SUMMARY

Learning Curve

Pythonic

C

C++

Others languages

Exceptions handling

Page 26: Python Bindings Overview

CYTHON

Page 27: Python Bindings Overview

CYTHON : PHILOSOPHY

Cython is an extension of Python language

Three simple steps :1. Write “python”2. Compile the module it with C compiler3. Import the package in your python code

Page 28: Python Bindings Overview

CYTHON

Compiling a module => setuptools

print “hello world!”

setup.py

from distutils.core import setupfrom distutils.extension import Extensionfrom Cython.Distutils import build_ext

setup( cmdclass = {'build_ext': build_ext}, ext_modules = [Extension(”hello", [”hello.pyx"])])

Page 29: Python Bindings Overview

CYTHON

cdef extern from "readline/readline.h": char* readline(char*) int add_history(char*)

def readline_loop(): while True: line = readline("c:\>”) if not line: break

add_history(line)

Page 30: Python Bindings Overview

CYTHON

setup.py

from distutils.core import setupfrom distutils.extension import Extensionfrom Cython.Distutils import build_ext

setup( cmdclass = {'build_ext': build_ext}, ext_modules = [Extension(‘readlineloop’,

[‘readline-loop.pyx’], libraries = [‘readline’])]

)

Page 31: Python Bindings Overview

CYTHON

Last details :

Can access C structures Possible to define callbacks Check on number of args Possible to wrap C++ classes! Handle exceptions! Can be used to optimize your code

need to learn a bit more

Page 32: Python Bindings Overview

CYTHON

Some limitations :

No support to yield No nested def No globals(), locals() Class / func can’t be placed inside control

structures

Page 33: Python Bindings Overview

CYTHON : SUMMARY

Learning Curve

Pythonic

C

C++

Others languages

Exceptions handling

Page 34: Python Bindings Overview

CONCLUSIONS

C API SWIG Ctypes Cython

Learning Curve

Pythonic

C

C++

Others languages

Exceptions handling