ctypes is a standard library for calling dynamic libraries from Python. Make a note of the lessons / addictive points you learned when using it for the first time recently.
When calling a function in a dynamic library, you need to specify a type that is compatible with C. (ref.) http://docs.python.jp/2/library/ctypes.html#ctypes-fundamental-data-types
This type is specified either when the function is called, or the return value / argument type is specified in advance by restype
/ ʻargtypes` before the call.
Type specification
from ctypes import *
#Specified at runtime
ret = test.func2(c_char_p("test"), c_char_p("test2"), c_char_p("test3"))
# restype/Specified by argtypes
test.func2.restype = c_char_p
test.func2.argtypes = (c_char_p, c_char_p, c_char_p)
ret = test.func2("test", "test2", "test3")
Since it becomes troublesome to specify at runtime as the number of calls increases, I think it is better to create a module that defines the interface of the library. Is it the same as the C header file?
interface.py
from ctypes import *
test.func1.restype = c_int
test.func2.argtypes = (None)
test.func2.restype = c_char_p
test.func2.argtypes = (c_char_p, c_char_p, c_char_p)
Structures are represented in the Python world by classes that inherit from ctypes.Structure
.
The members of the structure are specified in the __fields__
fields as an array of tuples. Tuples must be of the form (<field name>, <type>)
.
Structure and corresponding class
from ctypes import *
class JSON_T(Structure):
__fields__ = [('type', c_int), ('refcount', c_size_t)]
If you want to specify the pointer type of this structure, use the ctypes.POINTER
function.
(ref.)http://docs.python.jp/2/library/ctypes.html#ctypes.POINTER
Structure pointer type
from ctypes import *
class JSON_T(Structure):
__fields__ = [('type', c_int), ('refcount', c_size_t)]
test.func3.restype = c_char_p
test.func3.argtypes = (c_void_p, c_char_p, c_char_p, c_char_p, POINTER(JSON_T))
For types that originally represent pointers, such as ctypes.c_char_p
and ctypes.c_void_p
, you can use the ctypes.POINTER
function.
Pointer type of pointer(A type that originally represents a pointer)
from ctypes import *
test.func4.restype = c_char_p
test.func4.argtypes = (c_void_p, c_char_p, c_char_p, c_char_p, POINTER(c_void_p), POINTER(c_char_p))
When using these, it is necessary to give the variable specified by ctypes.c_char_p
/ ctypes.c_void_p
to the ctypes.byref
function to get a reference.
Handle pointer type arguments of pointers
from ctypes import *
test.func4.restype = c_char_p
test.func4.argtypes = (c_void_p, c_char_p, c_char_p, c_char_p, POINTER(c_void_p), POINTER(c_char_p))
#arg1 is already defined
arg2 = 'str2'
arg3 = 'str3'
arg4 = 'str4'
void_p_p = c_void_p(None)
char_p_p = c_char_p(None)
#If it is the following, NULL is assigned to the pointer of the pointer, so it is useless.
# void_p_p = None
# char_p_p = None
test.func4(arg1, arg2, arg3, arg4, byref(void_p_p), byref(char_p_p))
(Note) I don't know about the types that represent primitive types such as ctypes.c_int
because I haven't used them this time. Do you use the ctypes.POINTER
function twice?
Recommended Posts