如何将如下所示的C结构表示为python ctype并访问它?它将结构数组作为元素,并在另一个结构中使用-。
struct hello {
__s64 f1;
__u64 f2;
__u64 f3;
__s32 f4;
__u32 f5;
};
struct world {
__u64 f1;
__u64 f2;
__u16 f3;
__u16 f4;
__u32 f5;
struct hello h[0];
};
我尝试了以下方法,但不起作用:
from ctypes import *
class hello(Structure):
_pack_ = 1
_fields_ = [ ("f1", c_longlong),
("f2", c_ulonglong),
("f3", c_ulonglong),
("f4", c_long),
("f5", c_ulong)
]
class world(Structure):
_pack_ = 1
_fields_ = [ ("f1", c_ulonglong),
("f2", c_ulonglong),
("f3", c_uint16),
("f4", c_uint16),
("f5", c_uint32),
("f6", hello) #Is this correct?
]
发布于 2018-07-27 09:12:47
你所做的是不正确的。要使world
的最后一个成员成为N个hello
的数组,它的类型必须是hello * N
,而不是hello
。
但在这里,N是0,所以这并不是真的有效。
在C中,这被称为"struct hack“或"struct array hack”。该world
结构不是一个真正的结构,您可以按原样构造并传递它。相反,您要做的是非法锁定sizeof(world) + N * sizeof(hello)
字节,将其转换为world *
,然后传递该指针。因为数组索引在C中不做任何类型检查,所以my_world->h[2]
将会正常工作(假设您在world
的末尾至少为3个hello
分配了足够的内存)。
但它在Python中不起作用。
嗯,这是可行的,但你必须做更多的工作。
第一种选择是不在全局范围内实际定义world
,而是在每次需要处理world
时定义一个新的Structure
类。
例如。假设我们调用了一些函数,告诉我们有多少个hello:
n = lib.number_of_hellos()
现在我们想调用一个函数,它给我们提供了一个包含那么多问候的世界。所以:
class world(Structure):
_pack_ = 1
_fields_ = [ ("f1", c_ulonglong),
("f2", c_ulonglong),
("f3", c_uint16),
("f4", c_uint16),
("f5", c_uint32),
("f6", hello * n)
]
此时,您可以更改lib.get_world
的restype
以返回POINTER(world)
,也可以转换返回的结果。
或者,您可以将world
定义为始终具有1个hello
,但是随后,不是直接从world
指针访问hello
,而是在hello
的地址(或仅在world
的地址加上类型的hello
的偏移量;这两种方式都是相同的)处构造一个hello * N
指针。
如果您需要创建一个包含N个hello
的world来传递给C,该怎么办?
您可以再次使用第一个技巧,构造一个以N个hello
s数组结尾的新world
类,然后创建该类的一个实例将其传递给C。
或者,您可以使用C代码使用的相同技巧:保留全局单hello
world
类,然后通过创建缓冲区然后将其强制转换为world
来构造world
对象,或者通过构造world
对象然后在其上调用resize
来构造。
还有一些变通方法可以让你的生活更轻松。例如,如果您自己编写C代码(并且不能直接使用struct hack),那么可以很容易地将一对C函数添加到N-hello
world
中,反之亦然,这对C函数组成一个非hello
数组、一个hello
数组和一个world
。
或者,只需创建一个nonhackyworld
类型,在末尾有一个指向hellos数组的指针,而不是直接包含它,然后编写C函数在它们之间来回转换。
然后,您只需对这些函数执行ctypes
操作,并在需要传递或处理world
时调用它们(或者甚至将它们设置为其他函数的值类型转换器)。
即使你不能添加C函数,你也可以用ctypes
编写这些函数。它们将是创建缓冲区和强制转换指针的可怕丑陋的混乱,但您只需编写它们(并调试段错误)一次,然后到处使用它们。
https://stackoverflow.com/questions/51549340
复制相似问题