PyMaemo/Accessing APIs without Python bindings

m (PyMaemo/Introduction to Ctypes moved to PyMaemo/Introduction to ctypes: Page naming conventions. No CamelCase.)
Line 1: Line 1:
== Introduction ==
== Introduction ==
-
Sometimes you don't need a complete binding for some library, perhaps all you require is a couple functions that will solve your problem or make your program faster. For these cases, you can use ctypes to cherry-pick the needed functions and use them right away.
+
Sometimes you don't need a complete binding for some library, just a couple functions that will solve your problem. For these cases, you can use the <code>ctypes</code> module to cherry-pick the needed functions and use them inside Python, no further steps needed.
 +
 
 +
This page is not meant to be a complete <code>ctypes</code> guide; there is some great documentation at http://docs.python.org/library/ctypes.html.  
== Usage ==
== Usage ==
Line 11: Line 13:
  libc.printf('Hello world!')
  libc.printf('Hello world!')
-
In a few words, you create an object correspondent to the library you need and use it to call the function directly. Things can get complicated if the parameters or the return type are complex structures, though.
+
In a few words, you create an object correspondent to the library you need and use it to call the function directly. You can also store the functions in plain python objects to use them easily later:
 +
 
 +
c_printf = libc.printf
 +
c_printf('Hello libc')
 +
 
 +
Remember that those are C functions, not Python ones, so you must supply arguments of the correct type to avoid undefined behavior. As a example, if I pass an integer to the above function, I get
 +
 
 +
>>> c_printf(1)
 +
Segmentation fault (core dumped)
 +
 
 +
== Wrapping function arguments ==
 +
 
 +
Quoting http://docs.python.org/library/ctypes.html#calling-functions:
 +
 
 +
: None, integers, longs, byte strings and unicode strings are the only native Python objects that can directly be used as parameters in these function calls. None is passed as a C NULL pointer, byte strings and unicode strings are passed as pointer to the memory block that contains their data (char * or wchar_t *). Python integers and Python longs are passed as the platforms default C int type, their value is masked to fit into the C type.
 +
 
 +
For all other types, a <code>ctypes</code> C wrapper must be used; you can find them at http://docs.python.org/library/ctypes.html#fundamental-data-types.
 +
 
 +
An usage example of these wrappers is shown below:
 +
 
 +
>>> libc.printf("a integer: %d, a double: %f\n", 42, 3.14)
 +
Traceback (most recent call last):
 +
  File "<stdin>", line 1, in <module>
 +
ctypes.ArgumentError: argument 3: <type 'exceptions.TypeError'>: Don't know how  to convert parameter 3
 +
 
 +
Integers are fine, but <code>ctypes</code> can't handle Python doubles directly. <code>ctypes.c_double()</code> will solve the problem here:
 +
 
 +
>>> libc.printf("a integer: %d, a double: %f\n", 42, ctypes.c_double(3.14))
 +
a integer: 42, a double: 3.140000

Revision as of 14:20, 28 January 2010

Introduction

Sometimes you don't need a complete binding for some library, just a couple functions that will solve your problem. For these cases, you can use the ctypes module to cherry-pick the needed functions and use them inside Python, no further steps needed.

This page is not meant to be a complete ctypes guide; there is some great documentation at http://docs.python.org/library/ctypes.html.

Usage

Let's say you want to use libc's printf, for some reason. All you need in python is:

import ctypes
libc = ctypes.CDLL('libc.so.6')
libc.printf('Hello world!')

In a few words, you create an object correspondent to the library you need and use it to call the function directly. You can also store the functions in plain python objects to use them easily later:

c_printf = libc.printf
c_printf('Hello libc')

Remember that those are C functions, not Python ones, so you must supply arguments of the correct type to avoid undefined behavior. As a example, if I pass an integer to the above function, I get

>>> c_printf(1)
Segmentation fault (core dumped)

Wrapping function arguments

Quoting http://docs.python.org/library/ctypes.html#calling-functions:

None, integers, longs, byte strings and unicode strings are the only native Python objects that can directly be used as parameters in these function calls. None is passed as a C NULL pointer, byte strings and unicode strings are passed as pointer to the memory block that contains their data (char * or wchar_t *). Python integers and Python longs are passed as the platforms default C int type, their value is masked to fit into the C type.

For all other types, a ctypes C wrapper must be used; you can find them at http://docs.python.org/library/ctypes.html#fundamental-data-types.

An usage example of these wrappers is shown below:

>>> libc.printf("a integer: %d, a double: %f\n", 42, 3.14)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ctypes.ArgumentError: argument 3: <type 'exceptions.TypeError'>: Don't know how  to convert parameter 3

Integers are fine, but ctypes can't handle Python doubles directly. ctypes.c_double() will solve the problem here:

>>> libc.printf("a integer: %d, a double: %f\n", 42, ctypes.c_double(3.14))
a integer: 42, a double: 3.140000