Reputation: 826
I'm trying to use a function in a c library with the following prototype:
int glip_get_backends(const char ***name, size_t *count);
The name
argument here is the problem. It is a 2 dimmensional char array passed by reference. In C the function is used as follows:
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.
The most logical approach to me was doing this in 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'
The next approach was to use the POINTER()
function three times and omitting the byref()
, but that 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 the definition of backends
for some reason I don't fully comprehend has fixed the call, but the output I get is:
< ctypes.LP_c_char object at 0x7f4592af8710 >
< ctypes.LP_c_char object at 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.
Upvotes: 5
Views: 11023
Reputation: 826
After realizing that in the C implementation %s
is used to itterate over the 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 eryksun suggested. This way I can easily access the strings.
Upvotes: 6
Reputation: 3273
If backends members can use index
method, 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")])
Upvotes: -1