问题
我正在尝试使用具有以下原型(prototype)的 c 库中的函数:
int glip_get_backends(const char ***name, size_t *count);
这里的 name
参数是问题所在。它是一个通过引用传递的 2 维字符数组。在 C 中,该函数的用法如下:
const char** name;
size_t count;
glip_get_backends(&name, &count);
for (size_t i = 0; i < count; i++) {
printf("- %s\n", name[i]);
}
现在我想使用 ctypes 从 python 使用这个函数。
我尝试过的
对我来说最合乎逻辑的方法是在 python 中执行此操作:
lglip = CDLL("libglip.so")
count = c_int(0)
backends = POINTER(POINTER(c_char))
lglip.glip_get_backends(byref(backends), byref(count))
导致错误信息
TypeError: byref() argument must be a ctypes instance, not '_ctypes.PyCPointerType'
下一个方法是使用 POINTER()
函数三次并省略 byref()
,但这会导致以下错误:
ctypes.ArgumentError: argument 1: : Don't know how to convert parameter 1
然后我从this question中得到灵感并提出以下内容:
lglip = CDLL("libglip.so")
count = c_int(0)
backends = POINTER(POINTER(c_char))()
lglip.glip_get_backends(byref(backends), byref(count))
for i in range(0, count.value):
print backends[i]
在 backends
的定义之后添加 ()
出于某种原因我没有完全理解已经修复了调用,但我得到的输出是:
< ctypes.LP_c_char object at 0x7f4592af8710 >
< ctypes.LP_c_char object at 0x7f4592af8710 >
似乎我无法在 python 中使用一个迭代器迭代二维 c 数组,因为它没有正确地取消引用它。
最佳答案
在意识到在 C 实现中 %s
用于遍历子字符串后,我想出了以下可行的解决方案:
lglip = CDLL("libglip.so")
count = c_int(0)
backends_c = POINTER(c_char_p)()
lglip.glip_get_backends(byref(backends_c), byref(count))
backends = []
for i in range(0, count.value):
backends.append(backends_c[i])
print backends
更新:将 POINTER(POINTER(c_char))()
更改为 POINTER(c_char_p)()
,如 eryksun建议。这样我就可以轻松访问字符串。
关于python ctypes,通过引用传递双指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30324758/