I'm trying to use ctypes to create a char * array in python to be passed to a library for populating with strings. I'm expecting 4 strings back no more than 7 characters in length each.
My py code looks like this
testlib.py
from ctypes import *
primesmile = CDLL("/primesmile/lib.so")
getAllNodeNames = primesmile.getAllNodeNames
getAllNodeNames.argtypes = [POINTER(c_char_p)]
results = (c_char_p * 4)(addressof(create_string_buffer(7)))
err = getAllNodeNames(results)
lib.cpp
void getAllNodeNames(char **array){
DSL_idArray nodes; //this object returns const char * when iterated over
network.GetAllNodeIds(nodes);
for(int i = 0; i < (nodes.NumItems()); i++){
strcpy(array[i],nodes[i]);
}
}
I keep getting segmentation faults when I try to run this code. I've created a test from C that works perfectly but in Python I must be setting up the pointer array incorrectly or something. It seems to get to the second node in the loop and then have a problem as I've seen from spitting out data into the command line. Any insight would be much appreciated.
解决方案
The following code works:
test.py:
import ctypes
lib = ctypes.CDLL("./libtest.so")
string_buffers = [ctypes.create_string_buffer(8) for i in range(4)]
pointers = (ctypes.c_char_p*4)(*map(ctypes.addressof, string_buffers))
lib.test(pointers)
results = [s.value for s in string_buffers]
print results
test.c (compiled to libtest.so with gcc test.c -o libtest.so -shared -fPIC):
#include
void test(char **strings) {
strcpy(strings[0],"this");
strcpy(strings[1],"is");
strcpy(strings[2],"a");
strcpy(strings[3],"test!");
}
As Aya said, you should make sure there is room for the terminating zero. But I think your main problem was that the string buffer was garbage collected or something similar, as there was no direct reference to it anymore. Or something else is causing trouble in the creation process of the string buffers when no references are stored for them. For example this results in four times the same address instead of different addresses:
import ctypes
pointers = [ctypes.addressof(ctypes.create_string_buffer(8)) for i in range(4)]
print pointers