Странности с получением true/false из dll [решено]

Вопросы использования сторонних (не входящих в состав FPC и Lazarus) утилит и библиотек.

Модератор: Модераторы

Странности с получением true/false из dll [решено]

Сообщение trengtor » 29.05.2013 18:02:37

Столкнулся со странным™ явлением (FPC тут не виноват): есть API DLL для usb-железки (Velleman K8096), есть его функции и процедуры, расписанные в нотации Borland Pascal (DLL написан на Delphi).
Функции API возвращают boolean.
Типы прописаны корректно, в соответствии с описанием вендора.
Так вот что удивительно: не удается получать состояния. Изменять – да, а вот получить – увы, нет.
Ну т.е. там что ON, что OFF для параметра в железке установлено – все равно приходит false.
И что особенно удивительно™ – тестовая утилите вендора с той же самой API DLL работает как из пушки.
Задал вопрос на форуме поддержки, но особой надежды на ответ не питаю.

Никто не сталкивался с подобными закидонами? (не применительно к этому железу и API, а вообще)
Последний раз редактировалось trengtor 26.06.2013 18:42:07, всего редактировалось 1 раз.
Аватара пользователя
trengtor
новенький
 
Сообщения: 77
Зарегистрирован: 03.05.2013 08:57:43
Откуда: Москва

Re: Странности с получением true/false из dll

Сообщение alexey38 » 29.05.2013 18:24:37

Правильно ли указаны соглашения по вызову (cdecl, stdcall, pascal, safecall, fastcall и пр.)? Обычно подобные глюки возникают, когда в exe и dll указано по разному.
alexey38
долгожитель
 
Сообщения: 1627
Зарегистрирован: 27.04.2011 19:42:31

Re: Странности с получением true/false из dll

Сообщение trengtor » 29.05.2013 18:30:24

У вендора везде указан stdcall, его и использовал.
Код: Выделить всё
These are the declarations in borland pascal:

procedure SMCDisconnect; stdcall;
function SMCConnect(Port: PChar; Motors: DWORD): BOOL; stdcall;
procedure SMCSetTorque(Motor: DWORD; Enabled: BOOL); stdcall;
function SMCGetTorque(Motor: DWORD): BOOL; stdcall;

и т.п.

При этом SMCConnect возвращает как нужно, а вот SMCGetTorque – шиш. Только false.
Аватара пользователя
trengtor
новенький
 
Сообщения: 77
Зарегистрирован: 03.05.2013 08:57:43
Откуда: Москва

Re: Странности с получением true/false из dll

Сообщение Sergei I. Gorelkin » 29.05.2013 20:05:21

Возможна нестыковка в определении типа результата (BOOL). Он должен быть определен как LongBool с обоих сторон (и в Дельфи и FPC), если я все правильно понимаю.
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1395
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Re: Странности с получением true/false из dll

Сообщение trengtor » 29.05.2013 20:36:35

Sergei I. Gorelkin писал(а):Он должен быть определен как LongBool с обоих сторон

Попробовал. Не спасает.
Аватара пользователя
trengtor
новенький
 
Сообщения: 77
Зарегистрирован: 03.05.2013 08:57:43
Откуда: Москва

Re: Странности с получением true/false из dll

Сообщение alexey38 » 30.05.2013 04:13:22

trengtor писал(а):При этом SMCConnect возвращает как нужно, а вот SMCGetTorque – шиш. Только false.

В общем случае может быть две или три причины:
1. Вы неправильно работаете с железкой. Тут могут быть разные вариации. Например, нужно выполнять некие дополнительные операции по инициализации. Либо (что вполне вероятно), правильного результата нужно ждать. То есть API DLL работает в асинхронном режиме, и все функции API выполняет мгновенно, не дожидаясь ответа железки, чтобы не обтормаживать основную прогу. Тогда нужно делать цикл внутри которого есть Sleep(xxx), в котором непрерывно делать SMCGetTorque, пока тот не вернет истину. Это как работа с объектами ядра, можно в цикле получать значение Event, а можно использовать WaitForSingleObject, а если нет объектов синхронизации, то тогда только цикл.

2. Есть какие-то нюансы в части FPC/Lasarus (конечно это странно, но мало ли что). Тогда нужно попробовать тестовый пример на Дельфях или другом языке, для которого есть SDK API.

3. Сама API DLL использует какие-то виндовые технологии, типа обработчика событий (Message). Был как-то случай, уже плохо помню, там в API использовалась DDE, а у нас была консольная прога, не обрабатывающая WinMessage.
alexey38
долгожитель
 
Сообщения: 1627
Зарегистрирован: 27.04.2011 19:42:31

Re: Странности с получением true/false из dll

Сообщение trengtor » 30.05.2013 09:59:48

alexey38 писал(а):1. Вы неправильно работаете с железкой.

Я делаю то, что указано в API и описаниях. В самой железке стоит PIC, который и реализует логику работы. API существует в 2-х ипостасях: «официальный» .NET враппер для native API DLL и «полуофициальное» описание паскалевских вызовов для native API DLL на форуме поддержки. Каких-то дополнительных сведений там просто нет. Если посмотреть текст примера на VB – там тоже нет никаких циклов ожидания.

Пробую теребить поддержку изготовителя.

2. Есть какие-то нюансы в части FPC/Lasarus (конечно это странно, но мало ли что). Тогда нужно попробовать тестовый пример на Дельфях или другом языке, для которого есть SDK API.

Пробовали «потыкать» консольными «тестерами» на C++ и C#. С тем же результатом пока что. Что, согласитесь, странно.

3. Сама API DLL использует какие-то виндовые технологии, типа обработчика событий (Message). Был как-то случай, уже плохо помню, там в API использовалась DDE, а у нас была консольная прога, не обрабатывающая WinMessage.

Нет там в описании ничего подобного. Это не промизделие, а хоббикит от Velleman'а.
Аватара пользователя
trengtor
новенький
 
Сообщения: 77
Зарегистрирован: 03.05.2013 08:57:43
Откуда: Москва

Re: Странности с получением true/false из dll

Сообщение Sergei I. Gorelkin » 30.05.2013 11:36:35

Эти DLL и описания есть в Сети? Дай ссылку если есть.
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1395
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Re: Странности с получением true/false из dll

Сообщение trengtor » 30.05.2013 12:02:52

Вот, положил на дропбокс.

Добавлено спустя 1 час 9 минут 17 секунд:
Поддержка выдала свои ЦУ (включая correct Delphi unit for mtrapi32.dll), пошел их проверять.
Аватара пользователя
trengtor
новенький
 
Сообщения: 77
Зарегистрирован: 03.05.2013 08:57:43
Откуда: Москва

Re: Странности с получением true/false из dll

Сообщение Sergei I. Gorelkin » 30.05.2013 13:19:47

В файле mtrapi32.pas меняешь все слова Boolean на LongBool - все должно заработать.

Почему это так: переменная типа Boolean имеет размер 1 байт и ее численное значение может быть либо 0, либо 1. Этот тип специфичен для Паскаля, Си о нем ничего не знает.
Переменная типа LongBool имеет размер 4 байта и ее численное значение может быть любым, при этом 0 считается False, а все остальное - True. Этот тип предназначен специально для взаимодействия с Си и прочими языками.

DLL написана с расчетом на взаимодействие с Си и использует тип LongBool (это легко проверяется дизассемблером).
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1395
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Re: Странности с получением true/false из dll

Сообщение trengtor » 30.05.2013 13:59:32

Вот что пришло от саппорта: http://forum.velleman.eu/viewtopic.php? ... 536#p35534
В принципе, то же самое говорят.

Но ведь не работает, сволочь.
Вот консольный «тестер» (в mtrapi32 использован LongBool):

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

uses
  mtrapi32,
  Windows,
  Strings,
  Crt,
  FileUtil;

label
  Finish1;

var
  PortName: String;
  PortNameZLS: PChar;
  tmp_Result: LongBool;

begin
  Writeln (UTF8ToConsole('Тестирование подключения SMC K9086'));
  Writeln ('===');
  Write (UTF8ToConsole('Введите имя COM-порта (например, COM5): '));
  Readln (PortName);
  Writeln ('===');
  Writeln (UTF8ToConsole('Введено имя порта (тип string): '), PortName);
  Writeln ('===');
  Writeln (UTF8ToConsole('Преобразование имени порта из string в pchar'));
  PortNameZLS:= StrNew(PChar(PortName));
  Writeln (UTF8ToConsole('Имя порта, преобразованное из string в pchar :'), PortNameZLS);
  Writeln ('===');
  Write (UTF8ToConsole('Подключение к SMC по указанному порту: '));
  tmp_Result:= SMCConnect (PortNameZLS,1);
  case tmp_Result of
    TRUE : Writeln (UTF8ToConsole('Успешно'));
    FALSE: begin
      Writeln (UTF8ToConsole('Почему-то облом'));
      goto Finish1;
    end;
  end;
  Writeln (UTF8ToConsole('Нажмите любую клавишу'));
  ReadKey;
  Writeln ('===');
  Writeln (UTF8ToConsole('Смотрим состояние подключения: '), SMCConnected);
  Writeln (UTF8ToConsole('Нажмите любую клавишу'));
  ReadKey;
  Writeln ('===');
  tmp_Result:= SMCGetTorque (0);
  Writeln (UTF8ToConsole('Смотрим состояние TORQUE: '), tmp_Result);
  Writeln (UTF8ToConsole('Нажмите любую клавишу'));
  ReadKey;
  Writeln ('===');
  Writeln (UTF8ToConsole('Устанавливаем TORQUE')); SMCSetTorque (0,TRUE);
  Writeln (UTF8ToConsole('Нажмите любую клавишу'));
  ReadKey;
  tmp_Result:= SMCGetTorque (0);
  Writeln (UTF8ToConsole('Смотрим состояние TORQUE: '), tmp_Result);  // Вот здесь показывает FALSE. Абортим программу, смотрим тестовой утилитой: TRUE (WTF!)
  Writeln (UTF8ToConsole('Нажмите любую клавишу'));
  ReadKey;
  Finish1: Writeln ('===');
  Writeln (UTF8ToConsole('Гасим TORQUE и отключаемся'));
  Writeln (UTF8ToConsole('Нажмите любую клавишу'));
  ReadKey;
  SMCSetTorque (0,FALSE);
  SMCDisconnect;
  StrDispose (PortNameZLS);
end.


Прямо бесовщина какая-то ©
Аватара пользователя
trengtor
новенький
 
Сообщения: 77
Зарегистрирован: 03.05.2013 08:57:43
Откуда: Москва

Re: Странности с получением true/false из dll

Сообщение Sergei I. Gorelkin » 30.05.2013 14:39:30

Можно допустить неправильную работу Writeln(longbool), но это проверяется заменой на writeln(ord(tmp_result)).
А SMCSetTorque отрабатывает (мотор включается)?
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1395
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Re: Странности с получением true/false из dll

Сообщение trengtor » 30.05.2013 15:00:08

Да, включение отрабатывает нормально (и индикация есть в motordemo, и моторчик шипеть начинает), как и проверку отработки функции подключения, а также проверку подключения.

При использовании ord(tmp_result) показывает ноль, так что у Writeln все Ок с LongBool.
Аватара пользователя
trengtor
новенький
 
Сообщения: 77
Зарегистрирован: 03.05.2013 08:57:43
Откуда: Москва

Re: Странности с получением true/false из dll

Сообщение Sergei I. Gorelkin » 30.05.2013 15:38:30

Тогда я даже не знаю, что еще предположить... :(
Разве что брать в зубы отладчик и разбираться, что там происходит.
Можно еще попробовать откомпилить с помощью FPC 2.7.1 и сравнить ощущения...
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1395
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Re: Странности с получением true/false из dll

Сообщение trengtor » 30.05.2013 15:52:57

Хочу еще попробовать с поведением под Delphi сравнить.
(Поскольку саппорт бьет себя в грудь, что с предложенным ими вариантом враппера под Delphi все будет Ок.)

Добавлено спустя 2 часа 19 минут 22 секунды:
Быстренько собрал консольный тестер в D7 – то же самое поведение.
Проверил сделанное в FPC на ноутбуке (тоже W7-64) – то же самое поведение.
Мистика..

Добавлено спустя 3 часа 33 минуты 41 секунду:
На днях, как будет время, прогоню тесты для всех вызовов API, чтобы понять, кто из них возвращает свои параметры как положено, а кто – не хочет.

Добавлено спустя 13 часов 45 минут 58 секунд:
Sergei I. Gorelkin писал(а):Можно еще попробовать откомпилить с помощью FPC 2.7.1 и сравнить ощущения

Вопрос:
Как 2.7.1 прикрутить к Лазарусу?
Скачать fpcbuild и файлами из папки fpcbuildinstallbinw32 заменить аналогичные файлы в C:FPC2.6.2bini386-win32 ?

Добавлено спустя 4 часа 22 минуты 56 секунд:
В целях проверки попросил товарища написать «контрольку» на C# с использованием DLL через ее родной .NET-враппер.
Все чудесным образом работает. Мистика какая-то.
Аватара пользователя
trengtor
новенький
 
Сообщения: 77
Зарегистрирован: 03.05.2013 08:57:43
Откуда: Москва

След.

Вернуться в Сторонние средства

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 8

Рейтинг@Mail.ru