在64位环境中如何处理ctypes中的字符串数组(char **)?

1 投票
2 回答
2008 浏览
提问于 2025-04-16 12:24

我在用ctypes这个库在Python中处理libgphoto2。下面的代码在32位的机器上运行没问题,但在64位的机器上(Linux,Ubuntu)却出现了段错误(Segmentation Fault):

import ctypes

gp = ctypes.CDLL('libgphoto2.so')
a = gp.gp_library_version(0)
x = ctypes.c_char_p.from_address(a)
x.value

libphoto2、ctypes和Python都是从软件源安装的,所以我觉得问题可能出在我的代码上;我需要更全面地考虑指针之类的东西。gp_library_version()这个函数返回的是const char **,也就是一个字符串常量的数组。其他的gp_*函数运行得很好。

2 个回答

1

如果你在使用ctypes的时候没有对函数进行任何注释,系统会默认这些函数返回的是32位的整数。在32位的程序中,这些整数和指针大多数情况下是可以互换的,但在64位的程序中就不一定了。

在你的调用之前,只需要做一下

gp.gp_library_version.restype = ctypes.c_void_p

就可以了(你仍然需要那行x = ctypes.c_char_p.from_address(a))。

查看API文档,看看在使用完这个指针后是否需要自己释放它(在这种情况下,可能是需要的)。

3

问题在于,ctypes 默认认为所有函数返回的是 int 类型,也就是32位的整数。但是在64位系统上,指针是64位的,所以你会丢失指针返回值的高32位。当你尝试使用这个无效的指针时,就会出现段错误(segfault)。

你可以通过给函数的 restype 属性指定一个类型,来改变它的预期返回类型,方法如下:

gp = ctypes.CDLL('libgphoto2.so')
gp.gp_library_version.restype = ctypes.POINTER(ctypes.c_char_p)
a = gp.gp_library_version(0)
print a[0].value

撰写回答