首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >使用C结构数组的Python ctype定义

使用C结构数组的Python ctype定义
EN

Stack Overflow用户
提问于 2018-07-27 08:55:31
回答 1查看 110关注 0票数 2

如何将如下所示的C结构表示为python ctype并访问它?它将结构数组作为元素,并在另一个结构中使用-。

代码语言:javascript
复制
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];
           };

我尝试了以下方法,但不起作用:

代码语言:javascript
复制
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? 
              ]
EN

回答 1

Stack Overflow用户

发布于 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:

代码语言:javascript
复制
n = lib.number_of_hellos()

现在我们想调用一个函数,它给我们提供了一个包含那么多问候的世界。所以:

代码语言:javascript
复制
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_worldrestype以返回POINTER(world),也可以转换返回的结果。

或者,您可以将world定义为始终具有1个hello,但是随后,不是直接从world指针访问hello,而是在hello的地址(或仅在world的地址加上类型的hello的偏移量;这两种方式都是相同的)处构造一个hello * N指针。

如果您需要创建一个包含N个hello的world来传递给C,该怎么办?

您可以再次使用第一个技巧,构造一个以N个hellos数组结尾的新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编写这些函数。它们将是创建缓冲区和强制转换指针的可怕丑陋的混乱,但您只需编写它们(并调试段错误)一次,然后到处使用它们。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51549340

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档