Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Помогите с подключением к DLL / 17 сообщений из 17, страница 1 из 1
29.07.2019, 19:10
    #39842711
zeon11
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с подключением к DLL
Добрый день!

Пытаюсь подключиться к libpioneer3.dll, - DLL для работы с фискальным аппаратом Пионер 114ф.

В описании разработчик приводит пример инициализации сессии работы с ККТ по IP адресу на C++:

Код: plaintext
1.
int pioneer3_open (const char ∗host , uint16 timeout , const char∗ &response ) 



Параметры:
host IP-адрес ККТ
timeout таймаут ожидания ответа
response строка с результатом выполнения
Возвращает:
отрицательное число код ошибки
положительное число идентификатор сессии работы с ККТ, в дальнейшем
используется во всех командах.

Я попробовал перевести на Delphi:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
unit Un_Pioner;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Label1: TLabel;
    EditAddress: TEdit;
  
   
    procedure Button1Click(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
 
  private
    { Private declarations }
    Procedure ShowDLLError(IDSession: Integer);
  public
    { Public declarations }
  end;

type
  Tpioneer3_version           = procedure(var Amajor: Integer; var Aminor: Integer; var Amicro: Integer; var Abuild: Integer); stdcall;
  Tpioneer3_open              = function(AIp_Addr: PChar;     ATimeOut: Integer; var AResponce: PChar):Integer; stdcall;
 ..................................................

var
  Form1: TForm1;
  dll_handle:        THandle;
  IDSession : integer;

  pioneer3_version           : Tpioneer3_version          ;
  pioneer3_open              : Tpioneer3_open             ;
 
......................................

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var Responce: PChar; IPAddress: PChar;
begin            
  IPAddress:=PChar(EditAddress.Text);  //  '192.168.0.150'
  if Assigned(pioneer3_open)
       then begin
              IDSession:=pioneer3_open(IPAddress, 5000, Responce);
               // Здесь возвращает IDSession = -2
              if IDSession<0 then ShowDLLError(IDSession);
              ShowMessage(Responce);
            end;
end;

procedure TForm1.FormShow(Sender: TObject);
  var Amajor, Aminor, Amicro, Abuild : Integer;
begin
  dll_handle := LoadLibrary('libpioneer3.dll');

  if (dll_handle <= 0) then ShowMessage('LoadLibrary: libpioneer3.dll not found.')
    else
      begin
         @pioneer3_version           := GetProcAddress(dll_handle, 'pioneer3_version');
         @pioneer3_open              := GetProcAddress(dll_handle, 'pioneer3_open');
..................................................................

         if Assigned(pioneer3_version)
              then begin
                     pioneer3_version(Amajor, Aminor, Amicro, Abuild);
                     Label1.Caption:='Версия библиотеки Пионер: ' + IntToStr(Amajor)+'.'+IntToStr(Aminor)+'.'+IntToStr(Amicro)+'.'+IntToStr(Abuild);
                   end;
       end;
end;

procedure TForm1.ShowDLLError(IDSession: Integer);
var Mess: String;
begin
  case IDSession of
   -1: Mess:='Неправильный handle';
   -2: Mess:='Ошибка подключения к ККТ';
   -3: Mess:='Ошибка передачи данных в ККТ';
   -4: Mess:='Таймаут получения ответа из ККТ';
   -5: Mess:='Ошибка в размере пакета данных';
   -6: Mess:='Неправильная контрольная сумма пакета данных';
   -7: Mess:='Неправильный заголовок пакета данных';
   -8: Mess:='Ошибка в параметрах команды (при разборе JSON)';
    else Mess:='Не определённая производителем ККМ ошибка';
   end;
  showmessage(Mess+'/код возврата из функции библиотеки:'+IntToStr(IDSession));
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  FreeLibrary(dll_handle);
end;


end.



При запуске программы подключение к DLL проходит, о чём свидетельствует получение версии DLL,
однако попытка инициализации работы с ККТ по IP адресу дает "Ошибка подключения к ККТ" (-2).
Пинг аппарата по IP проходит.
Похоже, я напортачил с передачей параметров в функцию pioneer3_open, но разобраться где - не хватает опыта.

Помогите ПОЖ.!
...
Рейтинг: 0 / 0
29.07.2019, 19:24
    #39842715
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с подключением к DLL
Во-первых, в описании на С++ ничего не сказано о stdcall, следовательно это cdecl.
Во-вторых, параметр timeout - 16-ти разрядный, а твой Integer явно шире.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
29.07.2019, 20:12
    #39842727
zeon11
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с подключением к DLL
Dimitry SibiryakovВо-первых, в описании на С++ ничего не сказано о stdcall, следовательно это cdecl.
Во-вторых, параметр timeout - 16-ти разрядный, а твой Integer явно шире.



Да, в документации нашел:

Все команды имеют спецификацию вызова вида:
extern ”C” __declspec ( dllimport ) _cdecl
В дальнейшей документации при описании формата команд эта спецификация
опущена.


Переписал
Код: pascal
1.
2.
3.
type
  Tpioneer3_version  = procedure(var Amajor: Integer; var Aminor: Integer; var Amicro: Integer; var Abuild: Integer); cdecl;
  Tpioneer3_open     = function(const AIp_Addr: PChar; ATimeOut: UInt16;  var AResponce: PChar):Integer; cdecl;



Результат, увы, тот-же. Первая процедура выполняется, функция - нет.
...
Рейтинг: 0 / 0
29.07.2019, 20:38
    #39842729
X-Cite
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с подключением к DLL
3 параметр строка. А память под нее кто выделять должен?
...
Рейтинг: 0 / 0
29.07.2019, 20:51
    #39842733
ziv-2014
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с подключением к DLL
const char * = в делфи PAnsiChar
...
Рейтинг: 0 / 0
29.07.2019, 20:52
    #39842734
ziv-2014
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с подключением к DLL
Код: sql
1.
Tpioneer3_open     = function(const AIp_Addr: PAnsiChar; ATimeOut: UInt16;  var AResponce: PAnsiChar):Integer; cdecl;
...
Рейтинг: 0 / 0
29.07.2019, 21:10
    #39842736
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с подключением к DLL
zeon11Tpioneer3_open = function( const AIp_Addr: PChar;

Вот этот const ты совершенно зря сюда впихнул. И да, если у тебя Delphi юникодная, то оно
должно быть AnsiChar всюду.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
30.07.2019, 04:26
    #39842802
zeon11
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с подключением к DLL
Так заработало:

Код: pascal
1.
  Tpioneer3_open  = function(const AIp_Addr: PAnsiChar; ATimeOut: UInt16;  var AResponce: PAnsiChar):Integer; cdecl;

,

так тоже работает:
Код: pascal
1.
  Tpioneer3_open  = function(AIp_Addr: PAnsiChar; ATimeOut: UInt16;  var AResponce: PAnsiChar):Integer; cdecl;



Вызов функции:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
procedure TForm1.Button1Click(Sender: TObject);
var Responce: PAnsiChar; IPAddress: PAnsiChar;
begin
  IPAddress:='192.168.0.150';
  if Assigned(pioneer3_open)
       then begin
              IDSession:=pioneer3_open(IPAddress, 5000, Responce);
              if IDSession<0 then ShowDLLError(IDSession);
              showMessage(Responce);
            end;
end;



Под память под строку с ответом, как пишут разработчики, выделяет и освобождает библиотека.

Спасибо всем, помогли.
...
Рейтинг: 0 / 0
30.07.2019, 07:46
    #39842819
Vizit0r
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с подключением к DLL
аж интересно стало - как длл узнает, что память под строку уже можно освобождать?
...
Рейтинг: 0 / 0
30.07.2019, 09:34
    #39842837
ziv-2014
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с подключением к DLL
zeon11,
Учти с таким подходом у тебя будут утечки памяти.
...
Рейтинг: 0 / 0
30.07.2019, 09:41
    #39842838
ёёёёё
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с подключением к DLL
Vizit0rаж интересно стало - как длл узнает, что память под строку уже можно освобождать?
Например, предполагается общий диспетчер памяти, а освобожденнием занимается клиент библиотеки.
Либо спецметод библиотеки, а освобождение вызовом этого метода также на клиенте.
...
Рейтинг: 0 / 0
30.07.2019, 09:43
    #39842839
ёёёёё
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с подключением к DLL
ёёёёёVizit0rаж интересно стало - как длл узнает, что память под строку уже можно освобождать?
Например, предполагается общий диспетчер памяти, а освобожденнием занимается клиент библиотеки.
Либо спецметод библиотеки, а освобождение вызовом этого метода также на клиенте.
Скорее, второе:авторПод память под строку с ответом, как пишут разработчики, выделяет и освобождает библиотека.
...
Рейтинг: 0 / 0
30.07.2019, 09:50
    #39842841
Gator
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с подключением к DLL
Vizit0rаж интересно стало - как длл узнает, что память под строку уже можно освобождать?Попросить её (вызвать её процедуру, освобождающую память)?
...
Рейтинг: 0 / 0
30.07.2019, 10:28
    #39842854
vavan
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с подключением к DLL
Vizit0rинтересно стало - как длл узнает, что память под строку уже можно освобождать?может и никак а тупо при очередном вызове освобождается
...
Рейтинг: 0 / 0
31.07.2019, 07:30
    #39843243
zeon11
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с подключением к DLL
Вот в преамбуле к документации к библиотеке:

...........................
Все команды получают параметы и
возвращают ответ в виде null-терминированных строк. Память под строку с ответом выделяет и освобождает библиотека, поэтому нельзя освобождать указатель
на строку с ответом, а наоборот, для дальнейшего разбора рекомендуется скопировать строку ответа, выделив память в пользовательской программе.
Параметры и результаты выполнения оформлены в виде формате JSON, все
строковые данные должны быть в UTF-8.
............................
...
Рейтинг: 0 / 0
31.07.2019, 09:39
    #39843274
ziv-2014
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с подключением к DLL
zeon11, Тогда при объявлении переменных надо указывать ansistring(CP_UTF8).
...
Рейтинг: 0 / 0
31.07.2019, 09:41
    #39843276
vavan
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с подключением к DLL
zeon11, вполне согласуется с моим предположением. в либе случаем не предполагается несколько вызовов параллельно?
...
Рейтинг: 0 / 0
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Помогите с подключением к DLL / 17 сообщений из 17, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]