python ctypes,通过引用传递双指针

you*_*ate 3 c python ctypes

问题

我正在尝试使用具有以下原型的 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 数组进行迭代,因为它没有正确地取消引用它。

you*_*ate 5

在意识到在 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建议的那样。这样我就可以轻松访问字符串。