将字符串列表从python/ctypes传递到C函数,需要char**

ni65a41a  于 2022-12-11  发布在  Python
关注(0)|答案(5)|浏览(178)

我有一个C函数,它需要一个\0终止字符串列表作为输入:

void external_C( int length , const char ** string_list) { 
   // Inspect the content of string_list - but not modify it.
}

在python中(使用ctypes),我想基于python字符串列表调用此函数:

def call_c( string_list ):
    lib.external_C( ?? )

call_c( ["String1" , "String2" , "The last string"])

关于如何在python端构建数据结构,有什么提示吗?注意,我保证C函数不会改变string_list中字符串的内容。
此致
约阿金

wpcxdonn

wpcxdonn1#

def call_c(L):
    arr = (ctypes.c_char_p * len(L))()
    arr[:] = L
    lib.external_C(len(L), arr)
zbsbpyhn

zbsbpyhn2#

非常感谢您;我还做了一个类似这样的变化:

def call_c( L ):
    arr = (ctypes.c_char_p * (len(L) + 1))()
    arr[:-1] = L
    arr[ len(L) ] = None
    lib.external_C( arr )

然后在C函数中,我遍历了(char**)列表,直到找到一个NULL。

zzlelutf

zzlelutf3#

使用ctype

创建过期列表(字符串)

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'))

逻辑ctypes初始化长度为数组的指针

expiries_array = (ctypes.c_char_p * (len(expiries_bytes)+1))()

将字节数组赋给指针

expiries_array[:-1] = expiries_bytes
tcbh2hod

tcbh2hod4#

我只是使用SWIG类型Map
1.在demo.i接口文件中写入自定义类型Map。

%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.生成扩展

$ 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.导入python中的模块。

>>> from demo import yourfunction
nxowjjhe

nxowjjhe5#

这是一个很老的问题,但我认为值得补充,如果人们仍然搜索类似的问题。
使用numpy可能是处理所有低级操作和与库链接的最简单方法。

example = ["String1" , "String2" , "The last string"]
example_np = m = np.array(example, dtype=np.chararray)

当你构建char* 的numpy数组时,你可以直接用ctypes得到array(的指针,然后直接把它交给需要char**的库。

example_ptr = ctypes.cast(example_np.ctypes.data, ctypes.POINTER(ctypes.c_char_p)) # this is char**

你可以打电话给

lib.external_C(len(example), example_ptr)

相关问题