2017-11-17 158 views
0

我有一个C结构如下所示:ctypes:如何将结构数组定义为另一个结构的字段?

typedef struct _DXYZ { 
    DXYZSTATE State[]; 
} DXYZ, *PDXYZ 

本质上,的DXYZSTATE阵列,未知大小的。

当我试图在​​中声明这个结构时,我不知道该怎么做。

class DXYZ(Structure): 
    _fields_ = [ 
     ('State', ???) 
    ] 

我用什么来表示未知大小的结构数组?

如果有帮助,它在C中使用的示例如下,malloc'd与其他地方提供的大小。

CurrentState = (PDXYZ) malloc(statesize); 
err = update(CurrentState); 

更新过程使用结构填充预先分配的空间。

回答

2

这是一种方式,但它并不漂亮。​​不在结构中执行变量数组,因此访问变量数据需要进行一些转换。

test.c实现一个返回变量结构数据的测试函数。在这种情况下,我硬编码大小为4的返回数组,但它可以是任何大小。

#include <stdlib.h> 

typedef struct STATE { 
    int a; 
    int b; 
} STATE; 

typedef struct DXYZ { 
    int count; 
    STATE state[]; 
} DXYZ, *PDXYZ; 

__declspec(dllexport) PDXYZ get(void) 
{ 
    PDXYZ pDxyz = malloc(sizeof(DXYZ) + sizeof(STATE) * 4); 
    pDxyz->count = 4; 
    pDxyz->state[0].a = 1; 
    pDxyz->state[0].b = 2; 
    pDxyz->state[1].a = 3; 
    pDxyz->state[1].b = 4; 
    pDxyz->state[2].a = 5; 
    pDxyz->state[2].b = 6; 
    pDxyz->state[3].a = 7; 
    pDxyz->state[3].b = 8; 
    return pDxyz; 
} 

__declspec(dllexport) void myfree(PDXYZ pDxyz) 
{ 
    free(pDxyz); 
} 

test.py

from ctypes import * 
import struct 

class State(Structure): 
    _fields_ = [('a',c_int), 
       ('b',c_int)] 

class DXYZ(Structure): 
    _fields_ = [('count',c_int),  # Number of state objects 
       ('state',State * 0)] # Zero-sized array 

# Set the correct arguments and return type for the DLL functions. 
dll = CDLL('test') 
dll.get.argtypes = None 
dll.get.restype = POINTER(DXYZ) 
dll.myfree.argtypes = POINTER(DXYZ), 
dll.myfree.restype = None 

pd = dll.get() # Get the returned pointer 
d = pd.contents # Dereference it. 

print('count =',d.count) 
# Cast a pointer to the zero-sized array to the correct size and dereference it. 
s = cast(byref(d.state),POINTER(State * d.count)).contents 

for c in s: 
    print(c.a,c.b) 

dll.myfree(pd) 

输出:

count = 4 
1 2 
3 4 
5 6 
7 8 
+0

我不知道我完全理解,但它听起来像是这仅适用,如果我可以设置数据如何被建造。在我的情况下,我不控制数据;它是从第三方API返回的。这是否意味着我不能使用ctypes? – user1219358

+0

@ user1219358我构建了字节缓冲区以模拟您从API获取的内容。当我有机会时,我会用实际的C API更新示例。 –

+0

@ user1219358测试DLL的更新示例。 –

相关问题