Python向C共享库传递的指针被截断为32位问题求助
解决思路
1. 先排查共享库的编译位数
64位环境下如果编译时误加了-m32选项,生成的是32位共享库,64位Python调用时必然会出现指针截断。用命令验证:
file ./libptr_test.so
正常64位库会输出ELF 64-bit LSB shared object,如果显示32位,重新编译时去掉-m32,用标准命令:
gcc -shared -fPIC -o libptr_test.so ptr_test.c
2. 修正C代码的指针打印格式符
你用%x打印64位指针,本身就会截断低32位——%x是32位无符号十六进制格式符,64位环境下要改用%p(标准指针格式,自动适配位数)或者%lx(64位无符号十六进制):
#include <stdio.h> #include <stdint.h> void ptr_test(uint32_t *ptr) { printf("ptr_test: ptr = %p\n", (void*)ptr); // 或者用%lx显式打印64位地址 // printf("ptr_test: ptr = 0x%lx\n", (uint64_t)ptr); }
3. 调整Python代码的指针传递逻辑
你的Python代码里tbuf1[0].ctypes.data_as(POINTER(c_uint32))属于冗余操作,tbuf1本身就是二维数组,直接取整个数组的指针更准确,避免索引操作可能带来的类型隐式转换问题:
import ctypes import numpy as np PTR_TEST = ctypes.CDLL('./libptr_test.so') ptr_test = PTR_TEST.ptr_test ptr_test.restype = None ptr_test.argtypes = [ctypes.POINTER(ctypes.c_uint32)] tbuf1 = np.empty((1,1), dtype=ctypes.c_uint32) # 用016X完整显示64位地址 print("tbuf1 at 0x{:016X}".format(tbuf1.ctypes.data)) # 直接传递数组的指针 ptr_test(tbuf1.ctypes.data_as(ctypes.POINTER(ctypes.c_uint32))) del(PTR_TEST)
4. 验证ctypes类型匹配的正确性
虽然你已经设置了argtypes,可以换用c_void_p简化测试:把C函数改成void ptr_test(void *ptr),Python里设置ptr_test.argtypes = [ctypes.c_void_p],直接传递tbuf1.ctypes.data(整数类型的地址),这样可以排除指针类型不匹配的潜在问题。
5. 用C程序验证共享库本身
写个极简C测试程序,确认共享库在纯C环境下工作正常:
#include <stdio.h> #include <stdint.h> void ptr_test(uint32_t *ptr); int main() { uint32_t buf[1][1]; printf("C test: buf at 0x%lx\n", (uint64_t)buf); ptr_test(&buf[0][0]); return 0; }
编译运行:
gcc -o test_lib test_lib.c ./libptr_test.so ./test_lib
如果这里地址显示完整,说明问题出在Python调用环节;如果同样截断,那共享库编译肯定有问题。
内容的提问来源于stack exchange,提问作者mlCprog
相关产品推荐
相关产品推荐

