我试图将Python结构中的可变大小字符串传递到C代码中(或者更确切地说,传递到DLL/SO中)。C代码是由Matlab Coder生成的,因此我相当局限于更改C代码(尽管可以在Matlab中进行一些调整以更改输出)。
我在Python中使用ctypes来创建包含各种元素的结构,这是有效的,传递包含可变长度字符串的变量也是如此,但是,我不能让一个可变长度的字符串在一个结构中工作。
当在Matlab中创建字符串输入时,传递字符串效果很好。我通过ctypes将字符串传递到C类型定义中,如下所示:
Matlab生成的C代码:
/* Function Declarations */
extern double test_string_func(const char apa_vl_data[],
const int apa_vl_size[2]);
Python:
str2_in = "hyja"
bb = ct.c_char_p(str2_in.encode('utf-8'))
bb_sz = np.array([1, len(str2_in)]).astype(dtype=int)
bb_sz_p = bb_sz.ctypes.data
初始化并拨打电话:
libC.test_string_func.argtypes = [ct.c_char_p, np.ctypeslib.ndpointer()]
dbl_out = libC.test_string_func(bb, bb_sz)
但是,当我在Matlab(C和Python)中创建一个结构体时,我无法使调用工作:
C代码结构定义:
/* Type Definitions */
#ifndef struct_emxArray_char_T_1x10
#define struct_emxArray_char_T_1x10
struct emxArray_char_T_1x10 {
char data[10];
int size[2];
};
#endif /* struct_emxArray_char_T_1x10 */
#ifndef typedef_emxArray_char_T_1x10
#define typedef_emxArray_char_T_1x10
typedef struct emxArray_char_T_1x10 emxArray_char_T_1x10;
#endif /* typedef_emxArray_char_T_1x10 */
#ifndef typedef_struct0_T
#define typedef_struct0_T
typedef struct {
double val;
emxArray_char_T_1x10 str;
} struct0_T;
#endif /* typedef_struct0_T */
从头文件:
extern double test_string_func(const struct0_T *apa_struct);
我在Python中尝试过的许多方法之一:
class emxArray_char_T_1x10(ct.Structure):
""" creates a struct to match emxArray_char_T_1x10
C-code from Matlab:
/* Type Definitions */
#ifndef struct_emxArray_char_T_1x10
#define struct_emxArray_char_T_1x10
struct emxArray_char_T_1x10 {
char data[10];
int size[2];
}; """
_fields_ = [('data', ct.c_char_p),
('size', ct.POINTER(ct.c_int))]
class testInStruct(ct.Structure):
"""creates a struct to match struct in C file
C-code from Matlab:
/* Type Definitions */
typedef struct {
double val;
emxArray_char_T_1x10 str;
} struct0_T;
"""
_fields_ = [
("struct_input_val", ct.c_double),
("struct_input_str", emxArray_char_T_1x10),
]
# initialise struct data
input_string = "INPUT!!"
input_str = emxArray_char_T_1x10()
input_str.data = ct.c_char_p(input_string.encode('utf-8'))
# Pass a list of int
L = [1, len(input_string)]
arr = (ct.c_int * len(L))()
arr[:] = L
input_str.size = arr
sd = testInStruct()
sd.struct_input_val = 2.1
sd.struct_input_str = input_str
libC.test_string_func.argtypes = [ct.POINTER(testInStruct)]
dbl_out = libC.test_string_func(sd)
我已经成功地使相当复杂的结构工作,用不同的类型和数组作为输入。但是在结构中传递字符串时出错的原因我不知道。
更新:忘了说C代码在Python中调用时运行,但在C代码中产生不正确的字符串长度,并在C代码中尝试“fprintf”传递的字符串时退出代码。
你知道我会做错什么吗?
顺便说一下,这是具有可变长度变量的结构的标准格式,并且这些变量很容易处理:
struct emxArray_real_T
{
double *data;
int *size;
int allocatedSize;
int numDimensions;
boolean_T canFreeData;
};
2条答案
按热度按时间u4dcyp6a1#
Chris Luengo建议的更改有效,但需要进行一些额外的修改以使所有内容都能正常工作。如下所示:
emxArray_char_T_1x10部分应为:
而“initialize struct data”部分应该重新编写如下:
9rbhqvlz2#
C结构体
应该与Python中的Ctypes匹配为
注意
char* a
和char b[10]
的区别。是的,b
可以被看作是指向数组第一个元素的指针,但结构包含实际的数组,10个字符,而不是一个指向字符的指针。