5

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.

user17925
  • 989
  • 2
  • 10
  • 20
  • @user17925 any feedback on this one? – Gabi Purcaru Nov 06 '10 at 10:17
  • @Purcaru looks good; I worked your construction into my code and it worked! The python documentation provided that create_string_buffer helper function, so I guess I was just determined to use it. – user17925 Nov 08 '10 at 00:35

1 Answers1

9

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'
Gabi Purcaru
  • 30,940
  • 9
  • 79
  • 95