简体   繁体   English

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

[英]python ctypes, pass double pointer by reference

The Problem 问题

I'm trying to use a function in ac library with the following prototype: 我正在尝试使用以下原型在ac库中使用函数:
int glip_get_backends(const char ***name, size_t *count);
The name argument here is the problem. 这里的name参数是问题所在。 It is a 2 dimmensional char array passed by reference. 它是通过引用传递的2个dimmensional char数组。 In C the function is used as follows: 在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]);
}

Now I want to use this function from python using ctypes. 现在我想使用ctypes从python中使用这个函数。


What I've tried 我试过的

The most logical approach to me was doing this in python: 对我来说最合乎逻辑的方法是在python中执行此操作:

lglip = CDLL("libglip.so")
count = c_int(0)
backends = POINTER(POINTER(c_char))
lglip.glip_get_backends(byref(backends), byref(count))

which resulted in the error message 这导致了错误消息

TypeError: byref() argument must be a ctypes instance, not '_ctypes.PyCPointerType' TypeError:byref()参数必须是ctypes实例,而不是'_ctypes.PyCPointerType'


The next approach was to use the POINTER() function three times and omitting the byref() , but that results in the following error: 下一种方法是使用POINTER()函数三次并省略byref() ,但这会导致以下错误:

ctypes.ArgumentError: argument 1: : Don't know how to convert parameter 1 ctypes.ArgumentError:参数1 ::不知道如何转换参数1


Then I took inspiration from this question and came up with the following: 然后我从这个问题中汲取灵感并提出以下建议:

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]  

Adding () after the definition of backends for some reason I don't fully comprehend has fixed the call, but the output I get is: 由于某些原因我在backends的定义后添加()已经修复了调用,但我得到的输出是:

< ctypes.LP_c_char object at 0x7f4592af8710 > <ctypes.LP_c_char对象位于0x7f4592af8710>
< ctypes.LP_c_char object at 0x7f4592af8710 > <ctypes.LP_c_char对象位于0x7f4592af8710>

It seems I can't itterate over a 2 dimensional c array with one itterator in python, as it does not properly dereference it. 我似乎无法在python中使用一个itterator对二维c数组进行迭代,因为它没有正确地取消引用它。

After realizing that in the C implementation %s is used to itterate over the substrings I came up with the following working solution: 在意识到在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

Update: changed POINTER(POINTER(c_char))() to POINTER(c_char_p)() , as eryksun suggested. 更新:将POINTER(POINTER(c_char))()更改为POINTER(c_char_p)() ,如eryksun建议的那样。 This way I can easily access the strings. 这样我就可以轻松访问字符串。

If backends members can use index method, you can use this code: 如果后端成员可以使用index方法,则可以使用以下代码:

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 ''.join(backends[i][:backends[i].index("0")])

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM