Python ctypes中的多维字符数组(字符串数组)

5 投票
1 回答
8490 浏览
提问于 2025-04-16 06:35

我正在尝试通过ctypes将一个字符数组的数组传递给一个C语言的函数。

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

因为我用的数组是静态定义的,所以我只是修改了函数的声明和输入参数,像这样:

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

现在我遇到了一个问题,就是如何在Python中定义这个多维字符数组。我原本以为可以这样做:

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)

但是这给我带来了一个错误:TypeError: incompatible types, c_char_Array_4 instance instead of c_char_p instance。如果我把它改成:

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

那么我就会遇到段错误(segmentation faults)。而且,这看起来也不是构建二维数组的正确方法,因为如果我打印输入,我看到的是None

print input[0]
print input[1]

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

我还遇到了一个问题,就是在C文件中使用#DEFINE MY_ARRAY_X 2#DEFINE MY_ARRAY_Y 4来保持数组的维度,但我不知道怎么从libhello.so中提取这些常量,以便Python在构建数据类型时可以引用它们。

1 个回答

9

使用类似下面的东西:

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

简单的用法:

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

撰写回答