Читаю книгу "Библия Delphi" Фленова. Главу - "Явная загрузка DLL". вопрос этот может быть поднимался когда-то, поэтому заранее
извиняюсь, если повторюсь.
Есть код явной загрузки DLL и вызова функции из нее.
- Код: Выделить всё
{ CODE 1 }
//явный вызов библиотеки...
//создать тип для функции
type
Tfunction = function(Param:Pchar):Pchar; stdcall;
....
// в какой-то процедуре( пусть OnClick по кнопке) вызвать DLL и поискать в ней функцию
procedure Button.Click(Sender: Tobject);
var
Func:TFunction; // переменная для полученной из DLL функции
DLLHandle: THandle; //Хандл библиотеки
begin
//попытаться загрузить библиотеку в память
DLLHandle:=LoadLibrary('dll_2.dll');
// проверить , загрузилась ли DLL
if DLLHandle <> 0 then
begin
//библиотека нашлась и загрузилась в память.
//поискать в ней функцию. Если она найдется, то указать ее адрес переменной Func
@Func:=GetProcAddress(DLLHandle,'GetString');
//если указатель на Func не nil - функция нашлась в библиотеке и
//все должно было присвоиться
if @Func <> nil then
begin
//Что-то сделать с функцией
showmessage(Func('Печенька!'));
//Уничтожить библиотеку
FreeLibrary(DLLHandle);
end;
end
else
begin
// какой-то код , который будет работать,
// если DLL не загрузилась. Например, Записать ошибку в журнал логов...
end;
end;
Сама DLL написана в Borland Delphi 2.0. Вот ее код:
- Код: Выделить всё
{ CODE 2 }
library dll_2;
uses
SysUtils,
Classes;
//в DLL нельзя ( не рекомендуется ) использовать тип STRING , а надо тип PCHAR
function GetString(Param:Pchar):Pchar export stdcall;
begin
result:=Param;
end;
exports
GetString index 10 name 'GetString';
begin
end.
Теперь сформулирую суть проблемы:
{ CODE 1 } Написан в Borland Delphi 7. Компилируется и выполняется прекрасно. Никаких ошибок , предупреждений,
никаких Access Violation нету. Программа работает.
Набрав точно такой же код (скопипастив из Delphi) явного вызова этой DLL в Lazarus, получаю ошибку на этой строке:
- Код: Выделить всё
@Func:=GetProcAddress(DLLHandle,'GetString');
Текст сообщения об ошибке:
["intersect.pas(53,8) Error: Can't assign values to an address"]
Вот, собственно, и вопрос - Как правильно и безопасно делать явный вызов DLL в Lazarus ?
Если статически загружать, то работает:
- Код: Выделить всё
function GetString(Param: PChar):Pchar; stdcall; external 'dll_2.dll' index 10;
Но такой способ вызова для моей задачи не подходит.
Была попытка сделать так:
- Код: Выделить всё
type
Tfunction = function(Param:Pchar):Pchar stdcall;
...
procedure Button.Click(Sender: TObject);
var
PFunc:^TFunction;
Func:TFunction
DLLhandle:THandle;
begin
//Попытаться загрузить библиотеку
DLLHandle:=LoadLibrary('dll_2.dll');
//Библиотека загружена удачно?
if DLLHandle <> 0 then
begin
//GetProcAddress возвращает указатель!
Pfunc:=GetProcAddress('GetString');
//указатель ссылается куда-то ?
if PFunc <> nil then
begin
//присвоить содержимое адреса, на который ссылается указатель
//переменной Func
Func:=PFunc^;
//выполнить
showmessage(Func('Печенька!'));
end;
//уничтожить библиотеку
FreeLibrary(DLLHandle);
end;
end;
Компилируется без предупреждений, программа запускается. При событии OnClick авария - "Access Violation".
В Lazarus как-то по-другому реализован явный вызов? Спасибо ^_^