python使用ctypes调用c程序

3 篇文章 0 订阅
1 篇文章 0 订阅

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模式进行编译,才能打印出详细的报错位置。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值