Взаимодействие Python и C: динамическое изменение размеров типов - PullRequest
1 голос
/ 03 марта 2012

Я пытаюсь взаимодействовать с C в Python, и у меня есть следующий прототип функции:

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

Размер беззнакового символа определяется параметром size.Поэтому мне нужен способ динамического изменения размера буфера в Python, чтобы он соответствовал размеру, возвращенному при вызове функции.Мне было очень трудно это понять.

Из руководства Python ctypes :

"Это хорошо, но как можно получить доступ к дополнительным элементам, содержащимся в этом массиве?о 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 ]

3 голосов
/ 04 марта 2012

Вот пример того, что мы обсуждали.Этот код ожидает, что вызывающий объект выделит буфер.

Тестовый код (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 голос
/ 03 марта 2012

Если вы получаете указатель от C, вы можете индексировать соответствующий указатель ctypes так же, как указатель на C.

Если вам нужно выделить массив в Python, вы можете динамически создавать тип массива ctypes.

...