python中嵌入C运行时函数

2017-01-01 00:49

详细的文档看这里:https://docs.python.org/3.6/library/ctypes.html?highlight=ctypes#module-ctypes


需要注意的是文档中提到的几点:

cdll 中的C函数的调用约定是cdecl 的,windll 中的C函数的调用约定是stdcall 的,Windows API专用。

1、Note

Accessing the standard C library through cdll.msvcrt will use anoutdated version of the library that may be incompatible with the onebeing used by Python. Where possible, use native Python functionality,or else import and use the msvcrt module.

python 标准库中存在msvcrt 库,尽量是用msvct 模块中的接口而不是 ctypes.cdll.msvct中的接口。

2、ctypes tries to protect you from calling functions with the wrong numberof arguments or the wrong calling convention. Unfortunately this only works onWindows.

说明在windows是调用C语言函数还有优势呢。

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

cdll.msvcrt.xxx 函数的参数使用C语言的类型(ctypes.c_cXXX),当然用python的 None、int、btyes、str 类型能对应到C语言的NULL、int、char*, wchar*,实践中发现 wchar_t* ,貌似不是很好用,所以尽量只用python 的 bytes. 

ctypes 中的其他函数当然都是python 函数啦,所以使用时当然都是python 数据类型。

ctypes.cdll.msvcrt.printf(b"An int %d, a double %f\n", 1234, ctypes.c_float(3.14))
所以这里打印浮点数需要使用 ctypes.c_float().

当然也可以指定参数的类型,这样就能直接使用 3.14 作为参数,而不需要转换了。

printf.argtypes = [c_char_p, c_int, c_float]

3、By default functions are assumed to return the C int type. 

C标准库的 strchr 的第二个参数是 int 类型,所以下边这里需要使用 ord() 函数。

strchr.restype = c_char_p    # c_char_p is a pointer to a string
strchr(b"abcdef", ord("d"))

4、ctypes.byref() 函数用来产生一个C语言数据的指针,提供给cytpes.msvcrt.xxx 函数使用。当然使用ctypes.pointer() 函数也可以。

import ctypes
i = ctypes.c_int(0xffffffff)
ctypes.cdll.msvcrt.memset(ctypes.byref(i), 0, 4)
print(i.value)