python数组大小_Python Ctypes 0大小的数组?

I have look on many places for this, and have tried using cast, but had no success.

I have a struct in c like:

struct t{

int x;

struct y[0];

};

How would I resize the array of struct y? I tried the other types of this issue on SO (does python ctypes supports size-0 array?), but kept on getting this error.

TypeError: incompatible types, y_Array_20 instance instead of y_Array_0 instance

解决方案

My other answer you reference just has an example of returning a sized structure, and as the comments in that answer indicate, using a sized array time prevents accidently reading past the end of the array. This example below shows a way to size the array whether the DLL function returns one or the user creates one and passes it in.

test.c:

#include

#define API __declspec(dllexport)

typedef struct Test {

int size;

int arr[0];

} Test;

API int Test_use(Test* test) {

int sum = 0;

for(int i = 0; i < test->size; ++i)

sum += test->arr[i];

return sum;

}

API struct Test* Test_alloc(int size) {

struct Test* t = malloc(sizeof(struct Test) + size * sizeof(int));

if(t != NULL) {

t->size = size;

for(int i = 0; i < size; ++i)

t->arr[i] = i;

}

return t;

}

API void Test_free(struct Test* test) {

free(test);

}

test.py:

from ctypes import *

class Test:

# return a customized Test instance of the correct array size

def __new__(cls,size,*init):

if len(init) > size:

raise ValueError('too many initializers')

# "type" creates new types.

# type(name_of_type,bases,dict_of_attributes)

# It is instantiated with the size and initial array values.

return type(f'Test{size}', (Structure,), {

'_fields_': [('size',c_int),

('arr',c_int * size)]})(size,(c_int * size)(*init))

# This is the pointer type the functions need.

# In this case Test(0) returns a Test0 instance.

# "type" is used to get the type the pointer references.

PTEST = POINTER(type(Test(0)))

dll = CDLL('./test')

dll.Test_use.argtypes = PTEST,

dll.Test_use.restype = c_int

def Test_alloc(n):

# The DLL function returns the generate Test0 type,

# so this helper casts it to the TestN pointer type.

t = dll.Test_alloc(n)

return cast(t,POINTER(type(Test(t.contents.size))))

dll.Test_alloc.argtypes = c_int,

dll.Test_alloc.restype = PTEST

def Test_use(t):

# The DLL function needs the Test0 pointer type,

# so this helper casts it.

return dll.Test_use(cast(t,PTEST))

dll.Test_free.argtypes = PTEST,

dll.Test_free.restype = None

def Test_free(t):

# The DLL function needs the Test0 pointer type,

# so this helper casts it.

dll.Test_free(cast(t,PTEST))

t = Test_alloc(5)

print(type(t),t.contents.size,list(t.contents.arr))

print(Test_use(t))

Test_free(t)

n = Test(7,1,2,3)

print(type(n),n.size,list(n.arr))

print(Test_use(byref(n)))

Output:

5 [0, 1, 2, 3, 4]

10

7 [1, 2, 3, 0, 0, 0, 0]

6

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值