栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

python使用ctypes调用c程序

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

python使用ctypes调用c程序

ctypes地址截断问题

在使用ctypes开发python调用c程序的接口函数时,需要在python程序和c程序之间传递地址,不管是堆上的地址还是栈上的地址,如果没有设置函数的restype和argtypes时,很可能会引起Segment Fault错误。

这是因为在默认情况下,地址可能会被截断,导致访问地址时,访问到错误的地址,出现Segment Fault。

解决方法

在每个需要传递地址的地方,设置restype和argstype:

如:

myfunc.restype = ctypes.c_uint64 
myfunc.argtypes = [ctypes.c_uint64]

在设置argtypes时,如果有多个参数可以只设置部分参数的argtype。

也有说可以将restype设置为ctypes.c_void_p类型。

建议

我最初也没有每个函数都去设置restype和argtypes,发现在已有的测试代码都成功后,就觉得没有问题了,但是后面遇到了Segment Fault。这就建议我们在使用ctypes在python和c之间传递地址时,一定要设置restype和argtypes。

两种因为没有设置restype和argtypes有趣的报错经历:

  • 相同的一个函数接口,设置restype时,我在使用函数直接调用时,没有出现Segment Fault,但是在python传递的一个给c的回调函数中调用了这个函数,出现了Segment Fault。

  • 在普通Python环境和virtual env环境中都没有出现错误,但是在conda环境中直接Segment Fault。

使用gdb debug

在使用python ctypes调用c函数的时候,如果出现了Segment Fault等错误时,很难调试,特别是在python传递回调函数给c使用时。

两种调试的方法:

  • 在回调函数的情况,我只使用了打印的办法,暂时没有发现更好的办法。

在c++这边可以使用如下方法,打印出16进制地址:

std::cout << std::hex << ptrVar << std::endl;

在python这边:

print(hex(ptrVar))

通过对比地址是否一样,来判断是否出现地址截断问题。

  • 使用gdb
    使用gdb启动测试程序,
gdb -args python test_file.py

在gdb中执行run,执行程序,

run

当函数报错时,打印backtrace,

backtrace
// 或者使用缩写 bt

使用frame,展示栈帧

frame number

然后通过打印信息,处理解决报错问题。

注意: 在使用gdb调试的时候,c程序这边如果时so,则要使用debug模式进行编译,才能打印出详细的报错位置。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/920869.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号