What is ctypes?
Foreign function interface
Mechanism by which program written in one language can call routines
written in another. From Lisp, in Java known as Java Native
Interface (JNI).
Call C functions in a shared library/DLL from Python
- Similar technologies
- SWIG
- Boost.Python (heavy use of C++ templates)
- Pyrex
- weave.blitz and weave.inline
How is ctypes different?
- Clean separation between Python and C code
- ctypes can't wrap C++ classes, but this doesn't have to be an issue
- Develop your classes on the Python side of the fence
- Let your Python classes call C functions to get the job done
- Build C functions that do something using your C++ classes and call
these functions from Python
How do I use ctypes?
import ctypes
libc = ctypes.cdll['/lib/libc.so.6']
name = "John Doe"
libc.printf("Hello, %s!\n", name)
- restype and argtypes
- restype specifies the type your function returns
- argtypes specify the types of the function arguments
Example: Structure
struct svm_node {
int index;
double value;
};
from ctypes import Structure, c_int, c_double
class svm_node(Structure):
_fields_ = [('index', c_int), ('value', c_double)]
Example: restype and argtypes
struct node {
int index;
double value;
};
struct problem {
int l;
double *y;
struct node **x;
};
char* check_parameter(struct problem* prob, struct parameter* param);
from ctypes import Structure, POINTER, c_int, c_double
import numpy
class node(Structure):
_fields_ = [
('index', c_int),
('value', c_double)
]
class problem(Structure):
_fields_ = [
('l', c_int),
('y', POINTER(c_double)),
('x', POINTER(POINTER(node)))
]
_mylib = numpy.ctypeslib.load_library('mylib_', __file__)
_mylib.check_parameter.restype = c_char_p
_mylib.check_parameter.argtypes = [POINTER(problem), POINTER(parameter)]
argtypes and NumPy ndpointer
numpy.ctypeslib.ndpointer builds classes for use in a ctypes
function's argtypes list
Allows restrictions on arrays passed to wrapped function
- Can restrict any combination of:
- data type
- dimensionality
- shape
- flags (e.g. CONTIGUOUS, FORTRAN)
Invalid arrays will cause a TypeError to be raised
from numpy.ctypeslib import ndpointer
_mylib.myfunc.argtypes = [ndpointer(dtype=float64)]
_mylib.myfunc.argtypes = [ndpointer(ndim=2)]
_mylib.myfunc.argtypes = [ndpointer(shape=(10,10))]
_mylib.myfunc.argtypes = [ndpointer(flags='CONTIGUOUS')]
ctypes.pythonapi
- Call Python/C API functions from Python
- Useful for before diving into pure Python/C
- Example:
>>>> import ctypes
>>>> ctypes.pythonapi.Py_GetVersion.restype = ctypes.c_char_p
>>>> ctypes.pythonapi.Py_GetVersion()
'2.4.3 (#69, Mar 29 2006, 17:35:34) [MSC v.1310 32 bit (Intel)]'
>>>> from ctypes import pythonapi
>>>> from ctypes import py_object, c_char_p, c_void_p, c_int
>>>> pythonapi.PyInt_FromString.restype = py_object
>>>> pythonapi.PyInt_FromString.argtypes = [c_char_p, c_void_p, c_int]
>>>> x = ctypes.pythonapi.PyInt_FromString("ff", None, 16)
>>>> type(x)
<type 'int'>
>>>> print x
255