Была написана программа для работы с данными, собственно с самими данными работает подключаемая dllка, исходно dll загружалась "статически" при загрузке программы. При изменении программы так, чтобы dll загружалась динамически вылазит ошибка "access violation".
Попытался разобраться с этим на простенких програмках так и не понял в чем глюк.
Вот исходники прог на которых пытался разобраться:
DLL:
Код:
library dll;
uses
SysUtils, Classes, Windows, Math;
Type
Tdatabac = procedure(p1: pointer; p2: pointer; p3: pointer);
var
databac:tdatabac=nil;
{$R *.res}
Procedure init(adr:pointer); stdcall;
Begin
@databac:=adr;
End;
procedure simulate; stdcall;
var
t0,tx: integer;
datt, date, dati: double;
begin
t0:=gettickcount;
date:=0;
dati:=0;
while (gettickcount-t0)<1000 do
begin
datt:=gettickcount-t0;
date:=date+1;
dati:=date;
if @databac<>nil then databac(@datt,@date,@dati);
end;
end;
exports
simulate, init;
begin
end.
Код проги со статическим импортом DLL:
Код:
unit main;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
type
Tgetdata = procedure(d1: PDouble; d2: PDouble; d3: PDouble);
var
Form1: TForm1;
datt, date, dati: array [1..10000] of double;
pn:integer;
getdata: Tgetdata;
implementation
{$R *.dfm}
procedure init(adr: pointer); stdcall; external 'dll.dll';
procedure simulate; stdcall; external 'dll.dll';
procedure getd(d1: PDouble; d2: PDouble; d3: PDouble);
begin
if d1<>nil then datt[pn]:=d1^;
date[pn]:=d2^;
dati[pn]:=d3^;
form1.memo1.Lines.Add(floattostr(datt[pn])+' '+floattostr(date[pn])+' '+floattostr(dati[pn]));
pn:=pn+1;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
simulate;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
new(@getdata);
@getdata:=@getd;
init(@getdata);
pn:=1;
end;
end.
Код проги с динамическим импортом DLL:
Код:
unit main;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
type
Tgetdata = procedure(d1: PDouble; d2: PDouble; d3: PDouble);
type
Tsimulate = procedure;
type
Tinit = procedure(adr: pointer);
var
Form1: TForm1;
datt, date, dati: array [1..10000] of double;
pn:integer;
simulate : tsimulate;
getdata: Tgetdata;
init : Tinit;
LibHandle: HMODULE;
implementation
{$R *.dfm}
procedure getd(d1: PDouble; d2: PDouble; d3: PDouble);
begin
if d1<>nil then datt[pn]:=d1^;
date[pn]:=d2^;
dati[pn]:=d3^;
form1.memo1.Lines.Add(floattostr(datt[pn])+' '+floattostr(date[pn])+' '+floattostr(dati[pn]));
pn:=pn+1;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
@init := nil;
@simulate := nil;
LibHandle := LoadLibrary('dll.dll');
if LibHandle >= 32 then
begin
new(@getdata);
@getdata:=@getd;
init := tinit(GetProcAddress(LibHandle,'init'));
simulate := tsimulate(GetProcAddress(LibHandle,'simulate'));
if @init <> nil then init(@getdata);
if @simulate <> nil then simulate;
end;
while not application.Terminated do application.ProcessMessages;
FreeLibrary(LibHandle);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
pn:=1;
end;
end.
Сдается мне, что в случае динамического импорта прога как-то криво передает адрес процедуры обработчика в dllку. И как это исправить что-то не соображу...