When the dynamic/shared library is successfully loaded to the Python object, the common pattern is to store it as a module-level variable with the same name as the name of loaded library. The functions can be accessed as object attributes, so calling them is like calling a Python function from any other imported module, for example:
>>> import ctypes >>> from ctypes.util import find_library >>> libc = ctypes.cdll.LoadLibrary(find_library('c')) >>> libc.printf(b"Hello world!\n") Hello world! 13
Unfortunately, all the built-in Python types except integers, strings, and bytes are incompatible with C datatypes and thus must be wrapped in the corresponding classes provided by the ctypes module. Here is the full list of compatible datatypes that come from the ctypes documentation:
ctypes type |
C type |
Python type |
c_bool |
_Bool |
bool |
c_char |
char |
1-character bytes object |
c_wchar |
wchar_t |
1-character string |
c_byte |
char |
int |
c_ubyte |
unsigned char |
int |
c_short |
short |
int |
c_ushort |
unsigned short |
int |
c_int |
int |
int |
c_uint |
unsigned int |
int |
c_long |
long |
int |
c_ulong |
unsigned long |
int |
c_longlong |
__int64 or long long |
int |
c_ulonglong |
unsigned __int64 or unsigned long long |
int |
c_size_t |
size_t |
int |
c_ssize_t |
ssize_t or Py_ssize_t |
int |
c_float |
float |
float |
c_double |
double |
float |
c_longdouble |
long double |
float |
c_char_p |
char * (NUL terminated) |
bytes object or None |
c_wchar_p |
wchar_t * (NUL terminated) |
string or None |
c_void_p |
void * |
int or None |
As you can see, the preceding table does not contain dedicated types that would reflect any of the Python collections as C arrays. The recommended way to create types for C arrays is to simply use the multiplication operator with the desired basic ctypes type as follows:
>>> import ctypes >>> IntArray5 = ctypes.c_int * 5 >>> c_int_array = IntArray5(1, 2, 3, 4, 5) >>> FloatArray2 = ctypes.c_float * 2 >>> c_float_array = FloatArray2(0, 3.14) >>> c_float_array[1] 3.140000104904175
As syntax works for every basic ctypes type.
Let's look at how Python functions are passed as C callbacks in the next section.