我可以使用 pybind 加载外部 c++ dll 并调用函数吗?

Can I use pybind to load an external c++ dll and call functions?

我正在尝试连接 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)

这个 returns 代码 -3 有或没有参数。根据文档 -3 指的是 "Port cannot be opened"。但我可以看到端口并使用 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)

我无法访问您正在使用的代码,但假设您发布的签名是正确的:

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))