使用CFUNCTYPE调用C函数出现段错误,直接设置restype却正常是什么原因
段错误触发原因分析
该问题是两种ctypes函数声明方式的底层处理逻辑差异导致的,核心原因有两点:
1. 适用场景不匹配
CFUNCTYPE的设计初衷是定义Python回调函数的类型签名,方便把Python函数作为参数传递给C代码调用,并不推荐用来包装C侧的导出函数给Python调用。
加载动态库后直接获取函数对象,显式设置restype和argtypes的方式,是ctypes官方文档明确推荐的标准用法,会直接从动态库的符号表读取函数的底层信息,自动适配调用约定、参数对齐等架构相关的细节,兼容性最好。
2. 返回值截断问题
如果没有显式声明返回值类型,ctypes默认会将所有外部函数的返回值当作32位整型c_int处理。
第一种写法中虽然在CFUNCTYPE的参数里指定了返回值为c_char_p,但部分旧版本ctypes中,通过CFUNCTYPE包装从cdll加载的函数时,会继承原未声明函数的默认int返回值处理逻辑:在64位架构下,长度为8字节的字符串指针会被截断为4字节的整型值,转换成非法的内存地址,访问该地址时就会触发段错误。
第二种写法是直接修改函数对象的restype属性,优先级最高,不会出现指针截断的问题,因此可以正常执行。
内容的提问来源于stack exchange,提问作者Paul Lynn
相关产品推荐
相关产品推荐

