
最近接到一个需求,要用 python 封装一个 c 语言的 so 。好久没动过 C 语言了。
目前 c 程序调用调通了,代码如下:
#include <stdio.h> #include "fm_def.h" #include "fm_cpc_pub.h" static unsigned char dev_index = 0; static unsigned int dev_type = 0xE600; static unsigned int dev_flag = 0x00000002; static void * dev; int main() { unsigned int code = FM_CPC_OpenDevice(&dev_index,dev_type,dev_flag,&dev); printf("%d\n",code); } python 封装这边,用了 ctypes 库调用 so,代码如下:
#!/usr/bin/env python3 from ctypes import * cur = cdll.LoadLibrary('./libfmapiv100.so') dev_index = c_ubyte(0) dev_type = c_uint(0xE600) dev_flag = c_uint(0x00000002) dev = c_void_p() code = cur.FM_CPC_GetDeviceInfo(byref(dev_index), 7, 1, byref(dev)) print(code) 这段代码报错 Segmentation fault,查了下大概率是参数格式问题。 如果参数列表写成
code = cur.FM_CPC_GetDeviceInfo(dev_index, 7, 1, byref(dev)) 会返回 errorcode ( so 的错误代码),个人感觉是我第一个参数格式写的有问题。
求救啊!或者有什么别的方案也指导下!多谢!!
这边贴下最新的python代码:
#!/usr/bin/env python3 from ctypes import * dev_index = c_ubyte(0) dev_type = c_uint(0xE600) dev_flag = c_uint(0x00000002) dev = c_void_p() cur = cdll.LoadLibrary('./libfmapiv100.so') cur_get_device = cur.FM_CPC_GetDeviceInfo cur_get_device.argtypes = (c_ubyte, c_uint, c_uint, c_void_p) cur_get_device.restype = c_uint code = cur_get_device(dev_index, dev_type, dev_flag, byref(dev)) print(code) 结果为:code = 421060613 调用C库中另外一个翻译errorcode的接口结果如下:
FileName:api_main.c, Line:796 error parameter 所以还是(dev_index, dev_type, dev_flag, byref(dev))这里出了问题嘛,难道是空指针void *不能这样传入?这个空指针也是这个函数的出参。
1 Pagliacii 2020-06-29 11:37:30 +08:00 不应该是 ``` code = cur.FM_CPC_GetDeviceInfo(byref(dev_index), c_uint(7), c_uint(1), byref(dev)) ``` ? 通过调用 ctypes 的 c_uint 把 Python 中的数据对象转换成 C 中能识别的数据类型 |
2 Pagliacii 2020-06-29 11:40:27 +08:00 还有另一种写法就是声明 FM_CPC_GetDeviceInfo 的 argtypes 和 restype 。https://gist.github.com/Pagliacii/774ed5d3ea78a36cdb0754be6a25408d |
3 GYGYG OP |
4 GYGYG OP 解决了朋友们,我写错了接口名,导致的一直报错。现在的感受简直想挖个地洞钻进去,浪费了半天时间,系统复习了 C 的指针,算不亏把。。 |