Доступ к значению из обратного вызова в ctypes

0

Я использую Python/ctypes, чтобы написать приложение, основанное на коммерческой DLL. Эта DLL считывает файл flatfile и возвращает данные через struct s. Соответствующая struct C выглядит следующим образом:

struct System{
    unsigned short       user;
    unsigned short       version;
};

struct Message {
    unsigned short       header;
    unsigned short       data;
    unsigned int         messageType;
};

API, поставляемый с DLL, предоставляет указатель на функцию со следующим прототипом. Эта функция проходит через плоский файл и вызывает следующий вызов Callback:

typedef int (__stdcall *Process) (const char* filename, const char* base, unsigned int flags, int user, Callback stdcallback);

и прототип Callback (пятый аргумент выше) определяется как:

typedef int (__stdcall *Callback) (const System* Sys, const Message* Msg);

В моем файле python:

from ctypes import *

# using WinDLL for stdcall
lib = WinDLL('CVO.dll')

class System(Structure):
    _fields_ = [('user', c_ushort),
                ('version', c_ushort)]

class Message(Structure):
    _fields_ = [('header', c_ushort),
                ('data', c_ushort),
                ('messageType', c_uint)]

PROTO = WINFUNCTYPE(c_int, POINTER(System), POINTER(Message))

def py_callbck(Sys, Msg):
    print Msg._type_.messageType
    # return 0 to read the next line in the flatfile
    return 0

Callback = PROTO(py_callbck)

pProcess lib.Process
pProcess.argtypes = [c_char_p,c_char_p,c_uint,c_int,PROTO]
pProcess.restype = c_int

pProcess(c_char_p('flat.ccf'),c_char_p(None),c_uint(0),c_int(0),Callback)

Моя проблема заключается в доступе к значению, которое DLL передает в структуру Msg. Код должен печатать c_int (0, 1, 2), но вместо этого возвращает тип Field типа:

<Field type=c_ulong, ofs=136, size=4>

Я знаю, что файл flatfile обрабатывается, потому что мой код Python выводит сотни операторов <Field...>, которые он должен делать.

Мой вопрос в том, как я могу получить доступ к значению, которое DLL Msg Structure Msg вместо того, чтобы возвращать операторы <Field...>?

Заметьте, что я относительно новичок в ctypes и очень мало C, поэтому, если вы заметили проблемы с определением чего-либо, сообщите мне. Например, я знаю, что существует разница между ctypes.pointer который возвращает объект и ctypes.POINTER который возвращает новый тип. Когда я использую ctypes.pointer ошибки в коде.

Теги:
pointers
ctypes

1 ответ

1

Для того, чтобы быть относительно новым для ctypes, вы здесь неплохо справились. _type_ указателя является ссылкой на указанный в типе данных. В этом случае это Message. Атрибут class messageType - это CField данных CField используемый экземпляром.

Вместо этого вы хотите разыменовать указатель, чтобы получить экземпляр Message. Вы можете использовать индекс [0] или атрибут contents:

def py_callbck(Sys, Msg):
    print Msg[0].messageType  # Msg.contents.messageType
    # return 0 to read the next line in the flatfile
    return 0

Не забудьте сохранить ссылку на Callback чтобы он не собирался собирать мусор. В настоящее время вы ссылаетесь на нее как на глобальную. Это здорово.

Что касается способа, которым вы вызываете pProcess, обычно не нужно вручную создавать объекты ctypes для простых типов, когда вы определяете argtypes. Вы можете просто использовать следующее:

pProcess('flat.ccf', None, 0, 0, Callback)

Но обратите внимание, нужна ли функции перезаписываемому буферу строки. В этом случае используйте create_string_buffer. Здесь нет необходимости, поскольку параметры char * являются const.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню