Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multi-dimensional char array (array of strings) in python ctypes

I'm trying to pass an array of character arrays to a C function using ctypes.

void cfunction(char ** strings)
{
 strings[1] = "bad"; //works not what I need.
 strings[1][2] = 'd'; //this will segfault.
 return;
}

char *input[] = {"foo","bar"};
cfunction(input);

Since the array that I throw around is statically defined anyways, I just changed the function declaration and input parameter like so:

void cfunction(char strings[2][4])
{
 //strings[1] = "bad"; //not what I need.
 strings[1][2] = 'd'; //what I need and now it works.
 return;
}

char input[2][4] = {"foo","bar"};
cfunction(input);

Now I run into the problem of how to define this multi-dimensional character array in python. I had thought it would go like so:

import os
from ctypes import *
libhello = cdll.LoadLibrary(os.getcwd() + '/libhello.so')
input = (c_char_p * 2)()
input[0] = create_string_buffer("foo")
input[1] = create_string_buffer("bar")
libhello.cfunction(input)

This gives me TypeError: incompatible types, c_char_Array_4 instance instead of c_char_p instance. If I change it to:

for i in input:
 i = create_string_buffer("foo")

Then I get segmentation faults. Also this looks like the wrong way to build the 2d array because if I print input I see None:

print input[0]
print input[1]

# outputs None, None instead of "foo" and "foo"

I also run into the issue of using #DEFINE MY_ARRAY_X 2 and #DEFINE MY_ARRAY_Y 4 to keep the array dimensions straight in my C files, but don't know a good way to get these constants out of the libhello.so so that python can reference them when it constructs the datatypes.

like image 671
user17925 Avatar asked Nov 04 '10 21:11

user17925


1 Answers

Use something like

input = ((c_char * 4) * 2)()
input[0].value = "str"
input[0][0] == "s"
input[0][1] == "t" # and so on...

Simple usage:

>>> a =((c_char * 4) * 2)()
>>> a
<__main__.c_char_Array_4_Array_2 object at 0x9348d1c>
>>> a[0]
<__main__.c_char_Array_4 object at 0x9348c8c>
>>> a[0].raw
'\x00\x00\x00\x00'
>>> a[0].value
''
>>> a[0].value = "str"
>>> a[0]
<__main__.c_char_Array_4 object at 0x9348c8c>
>>> a[0].value
'str'
>>> a[0].raw
'str\x00'
>>> a[1].value
''
>>> a[0][0]
's'
>>> a[0][0] = 'x'
>>> a[0].value
'xtr'
like image 105
Gabi Purcaru Avatar answered Sep 18 '22 16:09

Gabi Purcaru