Страницы

Поиск по вопросам

пятница, 31 января 2020 г.

Функция из dll возвращает неверные значения Python

#python #delphi #dll #ctypes


Есть Dll(исходников нету), есть интерфейсный модуль к ней написанный на Delphi. Вызываю
функцию: 

function ProcessBonusListCountersPrint(vBonusCountersPrintQuery: TBonusCountersPrintQuery;
var vListCountersPrint: TListCountersPrint): Integer; stdcall;

type TBonusCountersPrintQuery = packed record
     Card: array[0..15] of char;

type TListCountersPrint = packed record         
     Lines: array[0..PACKET_COUNTERS_PR_MAX_LINE_COUNT - 1] of TCounterLine;

type TCounterLine = packed record
     LineNo: word;
     IsLast: byte;
     Num_Counter: word;
     N_Counter: array[0..9] of char;
     Value_Counter: Cardinal;


(Описание структур, функций беру из интерфейса)

На Python реализовал так:

from ctypes import *

class TBonusCountersPrintQuery(Structure):
_fields_ = [("Card", c_char * 15)]

class TListCountersPrint(Structure):
_fields_ = [("Lines", TCounterLine * 20)]

class TCounterLine(Structure):    
_fields_ = [("LineNo", c_int),
            ("IsLast", c_byte),
            ("Num_Counter", c_int),
            ("N_Counter", c_char * 11),
            ("Value_Counter", c_int)]

packet_counters_pr_max_line_count = 20;
i = 0;

ProcessBonusListCountersPrint = libc.ProcessBonusListCountersPrint

ProcessBonusListCountersPrint.argtype = [TBonusCountersPrintQuery, POINTER(TListCountersPrint)]
ProcessBonusListCountersPrint.restype = c_int32

vBonusCountersPrintQuery = TBonusCountersPrintQuery()
vBonusCountersPrintQuery.Card = b'123456798'

vListCountersPrint = TListCountersPrint()

res = ProcessBonusListCountersPrint(vBonusCountersPrintQuery, byref(vListCountersPrint))
print('ProcessBonusListCountersPrint', res)

for i in range(packet_counters_pr_max_line_count):
    if vListCountersPrint.Lines[i].IsLast == 1:
        break
    print(vListCountersPrint.Lines[i].Num_Counter, vListCountersPrint.Lines[i].N_Counter.decode('cp1251'),
vListCountersPrint.Lines[i].Value_Counter)


vListCountersPrint.Lines[i].N_Counter - возвращается правильное значение, а вот числовые
значения из этой структуры все неверные. Числовые типы все пробовал, ни один не дал
даже похожего результата.
Вопрос: как получить нужные мне данные?(в среде Borland Delphi 7 все работает)
    


Ответы

Ответ 1



Структуры в Python надо объявлять с параметром _pack_ = 1, поскольку в Delphi они объявлены как packed. Неправильно объявлены поля Card (15 байт, хотя в Delphi - 16) и N_Counter (11 байт, хотя в Delphi - 10). В структуре TCounterLine в Python использованы неправильные типы для LineNo и Value_Counter (в Delphi word - это 2-х байтовое беззнаковое целое, в ctypes для этого есть тип c_ushort).

Ответ 2



Совместил ответ от zed и tonal. В итоге получилась такая структура: class TCounterLine(Structure): _pack_ = 1 _fields_ = [("LineNo", c_short), ("IsLast", c_byte), ("Num_Counter", c_short), ("N_Counter", c_char * 10), ("Value_Counter", c_int)] Всё заработало. Большое спасибо за помощь)

Ответ 3



Вот так будет правильно: class TCounterLine(Structure): _fields_ = [("LineNo", c_short), # LineNo: word; ("IsLast", c_byte), # IsLast: byte; ("Num_Counter", c_short), # Num_Counter: word; ("N_Counter", c_char * 10), # N_Counter: array[0..9] of char; ("Value_Counter", c_int)] # Value_Counter: Cardinal;

Комментариев нет:

Отправить комментарий