[英]Passing a list of strings to from python/ctypes to C function expecting char **
I have a C function which expects a list \\0 terminated strings as input: 我有一个C函数,它期望list \\ 0终止的字符串作为输入:
void external_C( int length , const char ** string_list) {
// Inspect the content of string_list - but not modify it.
}
From python (with ctypes) I would like to call this function based on a list of python strings: 从python(使用ctypes)我想基于python字符串列表调用此函数:
def call_c( string_list ):
lib.external_C( ?? )
call_c( ["String1" , "String2" , "The last string"])
Any tips on how to build up the datastructure on the python side? 有关如何在python端构建数据结构的任何提示? Observe that I guarantee that the C function will NOT alter content of the strings in string_list.
注意我保证C函数不会改变string_list中字符串的内容。
Regards 问候
joakim 乔金 -
def call_c(L):
arr = (ctypes.c_char_p * len(L))()
arr[:] = L
lib.external_C(len(L), arr)
Thank you very much; 非常感谢你; that worked like charm.
这很像魅力。 I also did an alternative variation like this:
我还做了一个像这样的替代变体:
def call_c( L ):
arr = (ctypes.c_char_p * (len(L) + 1))()
arr[:-1] = L
arr[ len(L) ] = None
lib.external_C( arr )
And then in C-function I iterated through the (char **) list until I found a NULL. 然后在C函数中,我遍历(char **)列表,直到找到NULL。
expiries = ["1M", "2M", "3M", "6M","9M", "1Y", "2Y", "3Y","4Y", "5Y", "6Y", "7Y","8Y", "9Y", "10Y", "11Y","12Y", "15Y", "20Y", "25Y", "30Y"]
expiries_bytes = []
for i in range(len(expiries)):
expiries_bytes.append(bytes(expiries[i], 'utf-8'))
expiries_array = (ctypes.c_char_p * (len(expiries_bytes)+1))()
expiries_array[:-1] = expiries_bytes
I just make it using SWIG typemap 我只是使用SWIG typemap
1.write customized typemap in demo.i
interface file. 1.在
demo.i
接口文件中写入自定义的typemap。
%module demo
/* tell SWIG to treat char ** as a list of strings */
%typemap(in) char ** {
// check if is a list
if(PyList_Check($input))
{
int size = PyList_Size($input);
int i = 0;
$1 = (char **)malloc((size + 1)*sizeof(char *));
for(i = 0; i < size; i++)
{
PyObject * o = PyList_GetItem($input, i);
if(PyString_Check(o))
$1[i] = PyString_AsString(o);
else
{
PyErr_SetString(PyExc_TypeError, "list must contain strings");
free($1);
return NULL;
}
}
}
else
{
PyErr_SetString(PyExc_TypeError, "not a list");
return NULL;
}
}
// clean up the char ** array
%typemap(freearg) char ** {
free((char *) $1);
}
2.generate extension 2.生成扩展
$ swig -python demo.i // generate wrap code
$ gcc -c -fpic demo.c demo_wrap.c
$ gcc -shared demo.o demo_wrap.o -o _demo.so
3.import the module in python. 3.在python中导入模块。
>>> from demo import yourfunction
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.