Найти - Пользователи
Полная версия: Как при помощи ctypes читать из массива переменной длины?
Начало » Python для экспертов » Как при помощи ctypes читать из массива переменной длины?
1 2
bialix
Имеется Си объявление:

typedef struct CFMessageBase {
unsigned long msg_code;
unsigned long size;
unsigned char body[1];
} CFMessageBase, *PCFMessageBase;
Член структуры size указывает длину массива body.

Работа с такими структурами ведется в специальной Си-библиотеке. Я делаю обвертку к этой библиотеке при помощи ctypes (на Pyrex не получается, а гольный Python-C API слишком тяжело для меня).

Обвертка выглядит так:

class CFMessageBase(Structure):
_fields_ = [
('msg_code', c_ulong),
('size', c_ulong),
('body', c_uint8 * 1),
]
Теперь ломаю голову как мне вычитывать байты за пределами границ массива body, потому что ctypes строго следит за порядком:

a = CFMessageBase()

print a.body[1]

Traceback (most recent call last):
File "C:\Temp\1\test.py", line 14, in <module>
print a.body[1]
IndexError: invalid index
PS: Boost::Python не предлагать.
pyuser
class CFMessageBase(Structure):
_fields_ = [
('msg_code', c_ulong),
('size', c_ulong),
('body', c_ulong),]

a = CFMessageBase()
body = (c_uint8 * a.size).from_address(a.body)
for i in xrange(a.size): print(body[i])
bialix
body = (c_uint8 * a.size).from_address(a.body[0])
print (body)

<__main__.c_ubyte_Array_4 object at 0x00A9A3A0>
print body[0]
На этом месте получаю segmentation fault.
bialix
Метод from_address принимает собственно адрес. Непонятно как получить адрес a.body. Функция pointer дает указатель, но не адрес.
bialix
pyuser
class CFMessageBase(Structure):
_fields_ = [
('msg_code', c_ulong),
('size', c_ulong),
('body', c_ulong),]

a = CFMessageBase()
body = (c_uint8 * a.size).from_address(a.body)
for i in xrange(a.size): print(body[i])
Ваш код не работает. a.body – это значение, а не адрес.
pyuser
видимо я чего-то не понимаю, почему:
body = (c_uint8 * a.size).from_address(a.body[0]) # ???
атрибут body структуры обычный указатель поэтому я и объявил его как c_ulong
bialix
потому что атрибут body не является указателем. это массив байт.
bialix
a2 – это не массив, а только указатель на данные. А a1 – это живой массив.

Вы путаете имя массива с указателями.
pyuser
есть функция addressof
body = (c_uint8 * a.size).from_address(addressof(a.body))
bialix
точно, addressof помогла. работает.

Давно я на ctypes ничего не делал, позабывал всё.

pyuser – спасибо!
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB