Как настроить функцию обратного вызова для стандартной библиотеки Windows DLL в Python?Python

Программы на Python
Anonymous
Как настроить функцию обратного вызова для стандартной библиотеки Windows DLL в Python?

Сообщение Anonymous »

Я работаю над небольшой программой на Python для связи с преобразователем цифрового сигнала (FSU-SSBD от Mantracourt). По сути, модуль работает, считывая входные данные с подключенного тензодатчика и постоянно передавая их на подключенный компьютер с частотой 4800 Гц.
Но им также можно управлять напрямую (без специального программного обеспечения). ) с помощью простых команд по протоколу ASCII. Это то, чего я добиваюсь, потому что мне нужна частота гораздо ниже, чем 4800 Гц, и мне нужно регистрировать данные намного дольше, чем 30-минутный лимит при экспорте данных, полученных с помощью набора инструментов. Но - внимание, спойлер - у меня это не работает.
Модуль НЕ настроен на назначение COM-порта для связи, поэтому это не вариант. Вместо этого Mantracourt предоставляет драйвер DLL вместе с некоторой документацией, но я не могу правильно реализовать его в своей программе.
МОЯ ПРОГРАММА (минимальный рабочий пример):

Код: Выделить всё

import ctypes

class DLLCommunicator:

@ctypes.CFUNCTYPE(None,ctypes.c_int,ctypes.c_float)
def callback(station,value):
print(f"Station: {station}, Value: {value}")

def testDLL(self):
DLLpath = "C:\\Program Files (x86)\\FSUDrvXX DLL Driver\FSUDrv64.dll"
FSUDLL = ctypes.WinDLL(DLLpath)
FSUDLL.INITIALISE(self.callback)
res1 = FSUDLL.OPENPORT()
print(f"OpenPort: {res1}")
res2 = FSUDLL.DEVICECOUNT()
print(f"DeviceCount: {res2}")
FSUDLL.COMMANDMODE()
res3 = FSUDLL.READCOMMAND("OVAL")
print(f"OVAL: {res3}")

if __name__ == "__main__":
DLLTest = DLLCommunicator()
DLLTest.testDLL()
Как видно из кода, первым шагом является ИНИЦИАЛИЗАЦИЯ() DLL и предоставление адреса обратного вызова для получения выходных данных команд DLL. Затем вызывается функция OPENPORT(), чтобы открыть интерфейс FSU-SSBD для связи. Затем я вызываю COMMANDMODE(), чтобы переключить FSU-SSBD из состояния по умолчанию потоковой передачи данных в реальном времени с частотой 4800 Гц и в командный режим, где я затем смогу читать/записывать различные ASCII-команды, такие как «OVAL», который читает одно значение из модуля.
При запуске приведенный выше код выдает следующий результат:

Код: Выделить всё

OpenPort: -500 #("Cannot list USB Devices. Problem with USB bus.")
DeviceCount: 1 #("A long value indicating the number of detected FSU Modules", 1 is correct)
OVAL: -200 #("Error during read or write.")
Если я запускаю свою программу, когда FSU-SSBD отключен, вместо этого я получаю следующий вывод:

Код: Выделить всё

OpenPort: -600 #("The calibration information cannot be retrieved so streamed values may be  incorrect.")
DeviceCount: 0 #("A long value indicating the number of detected FSU modules", 0 is now correct)
OVAL: -200 #("Error during read or write.")
На мой взгляд, я могу четко установить контакт с модулем, поскольку он понимает и отвечает на мои вызовы функций DLL, а также знает, подключен модуль или нет. Это заставляет меня думать, что что-то не так с тем, как я пытаюсь настроить функцию обратного вызова.
В качестве дополнительной проблемы или дополнительной информации, программа аварийно завершает работу после последнего оператора печати. Я не знаю почему.
Я знаю, что это сложно (если не невозможно) воспроизвести, не имея под рукой реального модуля FSU-SSBD. Но я надеюсь, что кто-то, имеющий опыт взаимодействия с ctypes и DLL с Python, найдет время, чтобы просмотреть документацию DLL и найти места в моем коде. В конце документа приведены примеры объявлений для VBA, PureBasic и C.
Спасибо, что дочитали!

ОБНОВЛЕНО MWE:
Обновлено на основе комментариев @Mark Tolonens

Код: Выделить всё

import ctypes

class DLLCommunicator:
def __init__(self):
self.DLLpath = 'C:\\Program Files (x86)\\FSUDrvXX DLL Driver\FSUDrv64.dll'
self.CALLBACK = ctypes.CFUNCTYPE(None, ctypes.c_byte, ctypes.c_float)
self.cb = self.CALLBACK(self.callback)  # Wrap the bound method and save it as an attribute.
self.station = ""
self.value = ""

def callback(self, station, value):
self.station = station
self.value = value

def testDLL(self):
self.fsuDll = ctypes.WinDLL(self.DLLpath)
fsuInitialise = self.fsuDll.INITIALISE
fsuInitialise.argtypes = self.CALLBACK,  # Recommended so ctypes can typecheck parameters
fsuInitialise.restype = None            # Declares return type.
fsuInitialise(self.cb)

self.openPort = self.fsuDll.OPENPORT
self.openPort.argtypes = None
self.openPort.restype = ctypes.c_long
res1 = self.openPort()
print(f"OpenPort: {res1}")

if __name__ == '__main__':
DLLTest = DLLCommunicator()
DLLTest.testDLL()
Вывод оператора print в self.testDLL() по-прежнему равен -500, что означает «Невозможно составить список USB-устройств. Проблема с шиной USB».>

Подробнее здесь: https://stackoverflow.com/questions/760 ... -in-python

Вернуться в «Python»