【问题标题】:Complex structure of int32_t and char array in python ctypespython ctypes中int32_t和char数组的复杂结构
【发布时间】:2021-04-25 23:27:16
【问题描述】:

我正在尝试创建一个结构以在提供的 C 库 (DLL) 中使用, 如何定义以下结构(在文档中给出)?

#define A 10
#define B 20
typedef struct
{
int32_t size;
int32_t num;
char buf1[A][B];
char buf2[A][B];
char buf3[A][B];
} INSTRUCT;

我尝试使用 ctypes 在 python 中定义它是这样的:

from ctypes import*

char_buff1 = ((c_char * 10) * 20)
char_buff2 = ((c_char * 10) * 20)
char_buff3 = ((c_char * 10) * 20)


class INSTRUCT(Structure):
    _fields_=[("size",c_int32),("num",c_int32),("buf1",char_buff1),("buf2",char_buff2),("buf3",char_buff3)]

int32_t 可以在 ctypes 中替换为 c_int_32 吗? 定义结构的方法是否正确?

然后我尝试将结构的指针提供给 DLL 函数并检查它返回的内容,如下所示:

dlllib = CDLL("some.dll")
somefunction = dlllib.some_function
somefunction.argtypes = [POINTER(INSTRUCT)]

INSTRUCT().size
INSTRUCT().num
print(np.ctypeslib.as_array(INSTRUCT().buf1))

但是,我只能返回 0 并且没有被函数修改——等于在 C 函数调用之前定义的那个。

我不确定问题发生在哪个阶段,但是,没有错误,代码正常执行。 不幸的是,我没有可用的 C 代码,只有函数的输入参数。

最好的问候

【问题讨论】:

    标签: python c function structure ctypes


    【解决方案1】:

    数组定义错误。在ctypes 中,需要反转数组索引才能像 C 那样索引数组。例如,char buf[x][y] 在 Python 中与 ctypes 的等价物是 buf = (c_char * y * x)()。请注意,边界是相反的。否则,您的定义是正确的。

    请注意,使用c_char 将返回数组值的文本字符。如果您想要整数,请使用c_int8。我将在下面使用后者。

    例子:

    from ctypes import *
    import numpy as np
    
    A,B = 10,20
    ARRAY = c_int8 * B * A   # build as B,A
    
    class INSTRUCT(Structure):
        _fields_=[("size",c_int32),
                  ("num",c_int32),
                  ("buf1",ARRAY),
                  ("buf2",ARRAY),
                  ("buf3",ARRAY)]
    
    i = INSTRUCT()
    i.buf1[9][19] = 1  # access indices as A,B
    print(np.ctypeslib.as_array(i.buf1))
    
    [[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
     [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
     [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
     [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
     [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
     [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
     [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
     [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
     [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
     [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1]]  # 1 in correct location
    

    您的访问示例使用了 INSTRUCT(),它每次都会创建一个新的归零对象。创建一个实例并将其传递给一个函数,如下所示:

    dlllib = CDLL("some.dll")
    somefunction = dlllib.some_function
    somefunction.argtypes = [POINTER(INSTRUCT)]
    
    i = INSTRUCT()          # make an instance
    somefunction(byref(i))  # byref() passes address of a ctypes object.
    

    【讨论】:

    • 嗨,马克,非常感谢,是的,我不知道修改后的订单!虽然,我需要结构中的 3 个数组(bufs)是 char 而不是 int8,但如果我尝试了你的示例 char buf[x][y] --> (c_char * y * x)() 我得到了一个错误 TypeError: second item in _fields_ tuple (index 2) must be a C type
    • @Werefkin 使用 c_char * 20 *10 作为类型。尾随括号使其成为一个实例。在我的示例中,将 ARRAY 更改为 c_char * B * A
    猜你喜欢
    • 2021-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多