Python是胶水语言,能使用非常多的模块去实现很多跨语言跨平台的功能。下面就讲一下怎么在python中调用c语言函数。首先,Python无法直接解析C文件,所以就需要将c文件编译成动态库。
流程:
- 编写C语言文件 ,编译成动态库。
- 在python中加载这些动态库
- 调用函数,函数可以有返回值,使用ctype模块做转换。
编译库
通过python调用c函数,返回"hello,world" 字符串。新建c语言文件 hello.c:
1 #include <stdio.h>
2
3 char *print_hello()
4 {
5 return "hello,world";
6 }
编译成库
gcc -o hello.so --share hello.c
CDLL 和 WinDLL区别
ctypes提供了两个LibraryLoader:CDLL和WinDLL。
CDLL支持__cdecl,WinDLL支持__stdcall(仅限Windows)。
根据您在C库中使用的调用约定,您必须在Python中使用正确的LibraryLoader。
import ctypes as C
try:
lib = C.CDLL('/lib.dll')
except:
try:
lib = C.WinDLL('/lib.dll')
except:
print 'failed to load lib'
这段代码永远不会在Windows上运行,因为ctypes是一个惰性加载器,这意味着当你加载库时,他不会检查你选择的LibraryLoader是否匹配C库中的调用约定。
因此,您可以在python中加载一个使用__stdcall和CDLL的C库,并且ctypes不会引发任何错误。
只是在您尝试调用该C库中的函数时,ctypes将引发以下错误。
ValueError: Procedure called with not enough arguments (4 bytes missing) or wrong calling convention
这意味着您应该使用WinDLL而不是CDLL,反之亦然。
因为ctypes是一个懒惰的加载器,所以要确保使用正确的加载程序,具体取决于C库中使用的调用约定。
调用库
新建python文件 “test.py”
1 from ctypes import *
2
3 dll = CDLL("./hello.so")
4 dll.print_hello.restype = c_char_p
5 str = dll.print_hello()
6 print(string_at(str, 11))
执行python文件
1 python test.py
2 hello,world