Найти - Пользователи
Полная версия: Проблемы с подключением dll
Начало » Python для экспертов » Проблемы с подключением dll
1
MaximBMT
Есть задача подключить dll для управления прибором. Но в процессе реализации возникли сложности.
 from ctypes import *
from ctypes.wintypes import *
class dmQWORD(Structure):
	_fields_ = [
		('deviceType', DWORD),
		('deviceID', DWORD)
	]
class devModel(Structure):
	_fields_ = [
		('dmQWORD', POINTER(dmQWORD)),
		('dmChar', CHAR * 8)
	]
	
class AULDEVIDN(Structure):
	_fields_ = [
		("interface_type", INT),
		('id', DWORD),
		('devModel', POINTER(devModel)),
		('sn', BYTE * 16),
		('tag', DWORD),
		('HWDate', DWORD),
		('HWVers', DWORD),
		('PLISVers', DWORD),
		('dwReserved', DWORD),
		('deviceName', CHAR * 16)
	]
TANetInterface = {
			'aniUnknown': INT(-1), 
			'aniAUN': INT(0), 
			'ainAUN2': INT(1), 
			'aniALAN': INT(2), 
			'aniAEPP': INT(3), 
			'aniAVCOM': INT(4), 
			'aniAUXPR': INT(5),
			'aniCH372': INT(6),
			'aniUOWRI': INT(7),
			'aniULAN': INT(8)} #Тип интерфейса для связи
socketIndex = INT(-1) #(int)Индекс сокета устройства, -1 - сканировать все
AULInterface = TANetInterface['aniUnknown'] #Тип интерфейса для связи
deviceList = AULDEVIDN() 
listSize = INT(1) #(int)Размер списка переданного от функции
needSize = INT() #(int)Возвращает количество обнаруженных устройств
	
mydll = cdll.LoadLibrary("APS7315.dll")
ScanSocket = mydll.APS7315_ScanSocket
ScanSocket.restype = INT
ScanSocket.argtypes = [INT, INT, AULDEVIDN, INT, INT]
ScanSocket(socketIndex, AULInterface, byref(deviceList), listSize, byref(needSize))

Есть описание функции

ViStatus APS7315_ScanSocket (int socketIndex, TANetInterface AULInterface, AULDEVIDN *deviceList, int listSize, int *needSize);

Описание
Создает список всех доступных по технологии AULNet устройств на указанном сокете (параметр Socket Index) по указанному интерфейсу (AUL Interface).

Список параметров

socketIndex

Variable Type int
Индекс сокета, устройства на котором вы хотите обнаружить. Передайте здесь -1, чтобы сканировать весь список сокетов.
Величина по умолчанию: -1

AULInterface

Variable Type TANetInterface
Тип интерфейса, используемый для связи с AUL-устройством.
Определение типа:
/* Тип интерфейса */
typedef enum tagANetInterface {
aniUnknown =-1, /* неизвестный */
aniAUN = 0, /* стандартный драйвер AUNUSB */
aniAUN2, /* драйвер AUNUSB 2 */
aniALAN, /* драйвер AUNLAN */
aniAEPP, /* драйвер EPP-порта */
aniAVCOM, /* виртуальный COM-порт */
aniAUXPR /* USB Xpress */
} TANetInterface;

Передайте здесь aniUnknown (-1), чтобы сканировать весь список сокетов.
Величина по умолчанию: -1

deviceList

Variable Type AULDEVIDN (passed by reference)
указатель на заполняемый список найденных устройств. Список составляется из структур AULDEVIDN (размер структуры 56 байт), определенной следующим образом:
/* идентификационный блок AUL-устройства */
typedef struct tagAULDEVIDN
{
TANetInterface interface_type; // тип интерфейса
DWORD id; // идентификатор (индекс локального подключения)
union {
struct {
DWORD deviceType; // Идентификатор типа прибора
DWORD deviceID; // Идентификатор номера прибора
} dmDWORD;
LONGLONG dmQWORD; // Тип модели в виде 64-битного целого
char dmChar; // Тип модели в виде 8-символьной строки
} devModel;
BYTE sn; // строка серийного номера
DWORD tag; // используется по необходимости программистом
DWORD HWDate; //дата прошивки (в формате 0xDDMMYYYY)
DWORD HWVers; //версия прошивки (в формате 0xMaMiReBl)
DWORD PLISVers; //версия PLIS
DWORD dwReserved; //зарезервировано
} AULDEVIDN;

listSize

Variable Type int
Показывает размер переданного на заполнение списка описаний устройств (параметр Device List). Если выделенный размер не достаточен для описания всех обнаруженных при заданных условиях устройств, то список заполняется насколько возможно, а нужное число записей для полного списка возвращается в параметре Need Size.

needSize
Variable Type int (passed by reference)
Показывает количество обнаруженных при заданных условиях устройств.
Возвращаемое значение
Возвращается код ошибки, в случае успеха - EAPS7315_NO_ERROR. Для получения дополнительной информации воспользуйтесь функциями GetErrorMessage или error_message.

При выполнении кода питон крашится с ошибкой
Имя события проблемы: APPCRASH
Имя приложения: python.exe
Версия приложения: 3.6.150.1013
Отметка времени приложения: 585cd094
Имя модуля с ошибкой: python36.dll
Версия модуля с ошибкой: 3.6.150.1013
Отметка времени модуля с ошибкой: 585ccfcd
Код исключения: c0000005
Смещение исключения: 000b81a9
Версия ОС: 6.1.7601.2.1.0.256.48
Код языка: 1049
Дополнительные сведения 1: 0a9e
Дополнительные сведения 2: 0a9e372d3b4ad19135b953a78882e789
Дополнительные сведения 3: 0a9e
Дополнительные сведения 4: 0a9e372d3b4ad19135b953a78882e789

Есть предположение что я не правильно использую указатель, который я должен передать в функцию, а именно deviceList. Но если я правильно понял все должно работать. Подскажите, пожалуйста, может кто сталкивался.
py.user.next
MaximBMT
ViStatus APS7315_ScanSocket (int socketIndex, TANetInterface AULInterface, AULDEVIDN *deviceList, int listSize, int *needSize);

MaximBMT
 ScanSocket.argtypes = [INT, INT, AULDEVIDN, INT, INT]
Не соответствуют типы. Там два указателя и в ctypes.wintypes есть соотвествующие типы.
https://github.com/python/cpython/blob/master/Lib/ctypes/wintypes.py
PINT
MaximBMT
py.user.next спасибо за помощь. Тип указателя на int там есть, а вот указателя на структуру я там не нашел, да и не должно быть. Это должно быть что-то типа POINTER(AULDEVIDN) (в моем случае). Он ругается на несоответствие типов ValueError: Procedure called with not enough arguments (20 bytes missing) or wro
ng calling convention
(если я правильно его понял).
И если я правильно понимаю то, “.argtypes” это что-то типа прототипа функции. Как бы если типы не соответствуют, то питон начинает ругаться. А он у меня не ругается, а просто крашиться.
Я попробовал изменить тип последнего аргумента в “.argtypes” на PINT - результат тот-же
PEHDOM
MaximBMT, насколько я помню, если ты при вызове делаешь byref(deviceList) то в argtypes нужно использовать POINTER(AULDEVIDN) тоже со свторым параметром типа INT.
Както так:
 ScanSocket.argtypes = [INT, INT, POINTER(AULDEVIDN), INT, POINTER(INT)]
ScanSocket(socketIndex, AULInterface, byref(deviceList), listSize, byref(needSize))
MaximBMT
PEHDOM, спасибо большое. Но он так выдает ошибку ValueError: Procedure called with not enough arguments (20 bytes missing) or wro ng calling convention. Как я понял типы не соответствуют.
Может есть еще идеи?
MaximBMT
Интересно получается если через print вывести типы

в arguments
<class ‘ctypes.c_long’>, <class ‘ctypes.c_long’>, <class ‘__main__.LP_AULDEVIDN’>, <class ‘ctypes.c_long’>, <class ‘ctypes.wintypes.LP_c_long’>

в функции
<class ‘ctypes.c_long’> <class ‘ctypes.c_long’> <class ‘CArgObject’> <class ‘ctypes.c_long’> <class ‘CArgObject’>

То они разные. Не знаю как это может помочь, но вдруг какая идея придет.
MaximBMT
Думал может в Питоне глюк (всяко бывает). Запускал через 3.6 и 2.6 никакой разницы.
PEHDOM
Э-э-э вам же в качестве аргумента нужно подавать список структур, а вы подаете структуру.Даже если вы хотите получить 1 результат, нужно структуру в список из одного элемента запихнуть.
насколько я помню както так кажись это делается:
 deviceList = (AULDEVIDN()*1)()
а что надо в argtypes в таком случае писать я не помню
MaximBMT
PEHDOM по идее и будет 1 устройство. argtype принимает и не ругается AULDEVIDN*1. Но это, к сожалению, все равно не работает. питон ругается на то, что * не поддерживает подобные операнды.
Если я правильно понимаю, то цифра после звездочки определяет массив однотипных данных. То есть количество резервируемого места и по идее не должно быть никакой разницы есть там *1 или нет.
Но есть предположение что функция выдает слишком много данных а python столько не зарезервирвал. Т.е. я не правильно распределил память (предположительно не верно построил структуру AULDEVIDN) и си-шная функция пытается записать данные в область памяти которая для нее не зарезервированна. И из-за попытки обращения не к своему участку памяти wind'а завершает python.
PEHDOM
MaximBMT
Если я правильно понимаю, то цифра после звездочки определяет массив однотипных данных. То есть количество резервируемого места и по идее не должно быть никакой разницы есть там *1 или нет.
Да честно говоря я не знаю как там внутри вашей ДЛЛ идет обращение к элементам массива, но обычно если вы ожидаете список обьектов, а получаете обьект то у вас программа выдаст ошибку . Что в пайтоне что в Си синтаксис доступа к элемнтам спика весьма похож. Попробуйте на досуге.
Насчет структуры то что бросаетьсяв глаза:

1.'devModel' , POINTER(devModel) у вас указатель на структуру а должно по идее быть union. хотя они очень, очень похожи, есть нюанс, котороый может поломать всю работу… И кстати почему POINTER, вроде в мануале не написно то он указатель? Или я чтото пропустил?
2.Тоже касается POINTER(dmQWORD) в devModel, вроде у вас нигде не указано что там указатель
3. devMode в туториале union состоящий из трех элементов:
dmDWORD - структура из deviceType и deviceID
dmQWORD тип LONGLONG - Тип модели в виде 64-битного целого
dmChar тип char
У вас же из двух, один из котороых совсем не того типа котороый нужен. dmQWORD у вас ссылаеться на class dmQWORD а должен быть 64-битным целым.
а dmDWORD вообще нету
4. deviceName char*16 в структуре. Я вообще не вижу в мануале такого…

This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB