Python ctypes, pass double pointer by reference

Problem

I am trying to use a function in c library with the following prototype: The
int glip_get_backends(const char ***name, size_t *count);


argument name

here is the problem. It is a 2-dimensional char array passed by reference. In C, the function is used like this:

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.


What i tried

The most logical approach for me was in python:

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

      

resulting in an error message

TypeError: byref () must be an instance of ctypes, not `_ctypes.PyCPointerType '


The next approach was to use the function POINTER()

three times and omit byref()

, but this results in the following error:

ctypes.ArgumentError: argument 1 :: Don't know how to convert parameter 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 definition backends

for some reason I didn't fully understand, fixed the call, but the output I get is the following:

<ctypes.LP_c_char object at 0x7f4592af8710>
<ctypes.LP_c_char object at 0x7f4592af8710>

I can't seem to be able to iterate over a 2 dimensional array with one iterator in python, since it doesn't make it dereferenced.

+3


source to share


2 answers


After realizing what the C implementation %s

uses to repeat over substrings, I came up with the following working solution:

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 suggested by eryksun . This way I can easily access the strings.

+3


source


If backend elements can use the method index

, you can use this code:



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")])

      

-1


source







All Articles