我正在尝试使用具有以下原型的 ac 库中的函数:这里
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]);
}
Run Code Online (Sandbox Code Playgroud)
现在我想使用 ctypes 从 python 中使用这个函数。
对我来说最合乎逻辑的方法是在 python 中执行此操作:
lglip = CDLL("libglip.so")
count = c_int(0)
backends = POINTER(POINTER(c_char))
lglip.glip_get_backends(byref(backends), byref(count))
Run Code Online (Sandbox Code Playgroud)
这导致了错误消息
TypeError: byref() 参数必须是 ctypes 实例,而不是 '_ctypes.PyCPointerType'
下一个方法是使用该POINTER()函数三次并省略byref(),但这会导致以下错误:
ctypes.ArgumentError: 参数 1 :: 不知道如何转换参数 1
然后我从这个问题中汲取了灵感,并提出了以下内容:
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]
Run Code Online (Sandbox Code Playgroud)
()在由于backends某种原因我不完全理解的定义之后添加已修复调用,但我得到的输出是:
< 0x7f4592af8710 处的 ctypes.LP_c_char 对象 >
< 0x7f4592af8710 处的 ctypes.LP_c_char 对象 >
似乎我无法在 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
Run Code Online (Sandbox Code Playgroud)
更新:更改POINTER(POINTER(c_char))()为POINTER(c_char_p)(),正如eryksun建议的那样。这样我就可以轻松访问字符串。