Python和C互操作:动态调整ctypes的大小

时间:2012-03-03 08:20:07

标签: python pointers ctypes resize

我正在尝试与Python中的C互操作,我有以下函数原型:

int testout(unsigned char *test, int *size)

unsigned char的大小由size参数决定。所以我需要一种方法来动态调整Python中的缓冲区大小以调整函数调用返回的大小。这对我来说很难搞清楚。

来自Python ctypes manual

“这很好很好,但是如何访问此数组中包含的其他元素?由于该类型仍然只知道4个元素,因此访问其他元素时会出错:

>>> short_array[:]
[0, 0, 0, 0]
>>> short_array[7]
Traceback (most recent call last):
...
IndexError: invalid index
>>>

使用带有ctypes的可变大小数据类型的另一种方法是使用Python的动态特性,并根据具体情况(重新)定义所需大小后的数据类型。“

大!我得到IndexError:无效索引,就像示例所示。他们决定不展示如何正确地做到这一点! :)

有谁知道如何正确调整ctype的大小?

以下是我的示例代码,除了调整大小:

from ctypes import *

lib = "test.so"
dll = cdll.LoadLibrary(lib)
print "Testing pointer output"
dll.testout.argtypes = [POINTER(c_ubyte), POINTER(c_int)]
sizeout = c_int(0)
mem = (c_ubyte * 20)() 
dll.testout(mem, byref(sizeout))
print "Sizeout = " + str(sizeout.value)
for i in range(0,sizeout.value):
    print "Item " + str(i) + " = " + str(mem[i])

2 个答案:

答案 0 :(得分:3)

以下是我们讨论的一个例子。此代码期望调用者分配缓冲区。

测试代码(Windows)

// IN: test=pre-allocated buffer.
// IN: size=size of pre-allocated buffer.
// RETURNS: 0 and size set to required size.
//          1 and size set to size used.
__declspec(dllexport) int testout(void *pdata, int *psize)
{
    unsigned char * p = (unsigned char *)pdata;

    if (*psize < 5)
    {
        *psize = 5; // set size required
        return 0;  // fail
    }

    p[0] = 123;
    p[1] = 255;
    p[2] = 237;
    p[3] = 12;
    p[4] = 222;
    *psize = 5; // indicate size used

    return 1;  // pass
}

的Python

from ctypes import *

test = CDLL('test')
size = c_int(0)
test.testout.argtypes=[c_void_p,POINTER(c_int)]
print "Result of NULL pointer and zero size:",test.testout(None,byref(size))
print "Returned size:",size.value
mem = (c_ubyte * 2)()
size = c_int(sizeof(mem))
print "sizeof(mem):",size.value
print "Result of small buffer:",test.testout(byref(mem),byref(size))
print "Returned size:",size.value
mem = (c_ubyte * size.value)()
print "Result of exact size buffer:",test.testout(byref(mem),byref(size))
print "Returned size:",size.value
for i in range(size.value):
    print mem[i]
mem = (c_ubyte * 20)()
size = c_int(20)
print "Result of bigger buffer:",test.testout(byref(mem),byref(size))
print "Returned size:",size.value
for i in range(size.value):
    print mem[i]

输出

Result of NULL pointer and zero size: 0
Returned size: 5
sizeof(mem): 2
Result of small buffer: 0
Returned size: 5
Result of exact size buffer: 1
Returned size: 5
123
255
237
12
222
Result of bigger buffer: 1
Returned size: 5
123
255
237
12
222

答案 1 :(得分:1)

如果从C接收指针,则可以像C指针一样索引相应的ctypes指针。

如果需要在Python中分配数组,可以动态创建适当大小的ctypes数组类型。