Могу ли я использовать pybind для загрузки внешней библиотеки DLL c ++ и вызова функций? - PullRequest
1 голос
/ 29 января 2020

Я пытаюсь взаимодействовать с терминалом PoS, который предоставляет только dll (c ++). Могу ли я использовать pybind для загрузки библиотеки DLL и вызова функции API с помощью некоторого кода, например:

import pybind11

mydll = pybind.load("/path/to/dll")

mydll.api_call(param1,param2)

Я попробовал следующий код в ctypes. Но не удалось заставить работать API или получить четкую ошибку.

from ctypes import *
import ctypes.wintypes as wintypes
mydll = windll.LoadLibrary("C:\madaapi_v1_7.dll")
mydll.api_GetCOMTerminalID.argtypes = POINTER(c_char_p), POINTER(wintypes.DWORD), POINTER(c_byte), POINTER(c_byte),POINTER(c_byte),POINTER(c_char_p),POINTER(c_int),POINTER(c_byte)


bPort,dwBaudRate,bParity,bDataBits,bStopBits, inReqBuff, inReqlen, terminal_id = c_char_p(b'COM3'),wintypes.DWORD(38400),c_byte(0),c_byte(8),c_byte(1),c_char_p(b'07!'),c_int(3),c_byte()

conn = mydll.api_GetCOMTerminalID(byref(bPort),byref(dwBaudRate),byref(bParity),byref(bDataBits),byref(bStopBits),byref(inReqBuff),byref(inReqlen),byref(terminal_id))
print(conn)

Возвращает код -3 с параметрами или без них. Согласно документации -3 «Порт не может быть открыт». Но я вижу порт и открываю его с помощью PySerial.

Согласно документу dll, это входные типы данных:

int api_GetCOMTerminalID (BYTE bPort, DWORD dwBaudRate, BYTE bParity, BYTE bDataBits, BYTE bStopBits, unsigned char* inReqBuff, int *inReqLen, BYTE *terminalId)

Вот пример вызова:

api_GetCOMTerminalID (3,38400,0,8,0,”07!”,3)

1 Ответ

1 голос
/ 02 февраля 2020

У меня нет доступа к коду, который вы используете, но при условии, что эта подпись, которую вы разместили, верна:

int api_GetCOMTerminalID (BYTE bPort, DWORD dwBaudRate, BYTE bParity, BYTE bDataBits, BYTE bStopBits, unsigned char* inReqBuff, int *inReqLen, BYTE *terminalId)

Тогда следующий код ctypes получит все типы правильно:

from ctypes import *
import ctypes.wintypes as wintypes

BYTE      = wintypes.BYTE
DWORD     = wintypes.DWORD
c_uchar_p = POINTER(c_ubyte)
c_int_p   = POINTER(c_int)
c_BYTE_p  = POINTER(BYTE)

mydll = windll.LoadLibrary("C:\madaapi_v1_7.dll")
mydll.api_GetCOMTerminalID.argtypes = \
    (BYTE,          # BYTE bPort
     DWORD,         # DWORD dwBaudRate
     BYTE,          # BYTE bParity
     BYTE,          # BYTE bDataBits
     BYTE,          # BYTE bStopBits
     c_uchar_p,     # unsigned char* inReqBuff
     c_int_p,       # int *inReqLen
     c_BYTE_p,      # BYTE *terminalId
mydll.api_GetCOMTerminalID.restype = c_int

И пример использования:

bPort, dwBaudRate, bParity, bDataBits, bStopBits = \
    BYTE(3), DWORD(38400), BYTE(0), BYTE(8), BYTE(0)
inReq        = b'07!'
inReqBuff    = (c_ubyte * len(inReq))()
for i in range(len(inReq)):
    inReqBuff[i] = int(inReq[i])
inReqLen     = c_int(3)
terminal_id  = BYTE(0)

conn = mydll.api_GetCOMTerminalID(bPort, dwBaudRate, bParity, bDataBits, bStopBits,
                                  inReqBuff, byref(inReqLen), byref(terminal_id))
...