imho.ws
IMHO.WS  

Вернуться   IMHO.WS > Компьютеры > Программирование
Опции темы
Старый 19.02.2007, 13:00     # 1
lyuq
Member
 
Аватар для lyuq
 
Регистрация: 15.06.2003
Адрес: underneath it all
Пол: Male
Сообщения: 348

lyuq Молодецlyuq Молодецlyuq Молодец
Указатели в Delphi

Была написана программа для работы с данными, собственно с самими данными работает подключаемая 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ку. И как это исправить что-то не соображу...
__________________
Сердце раскололось на тысячи искр, разжигая огонь угасающих глаз, бесконечно смотрящих на холодный свет звезд, не знающих страсти, любви и печали.(c)я
lyuq вне форума  
Старый 19.02.2007, 18:27     # 2
Павел
Guest
 
Сообщения: n/a

У тебя в dll соглашение вызова функций stdcall. При статическом импорте ты указал его. При динамическом – нет. Т.е. определение процедурных типов у тебя должно выглядеть следующим образом:

Код:
Type
  Tgetdata = procedure(d1: PDouble; d2: PDouble; d3: PDouble) stdcall;

type
  Tsimulate = procedure stdcall;

type
  Tinit = procedure(adr: pointer) stdcall;
 
Старый 19.02.2007, 18:42     # 3
lyuq
Member
 
Аватар для lyuq
 
Регистрация: 15.06.2003
Адрес: underneath it all
Пол: Male
Сообщения: 348

lyuq Молодецlyuq Молодецlyuq Молодец
Это называется тупизм напал. Все перепробовал, а на это даже не глянул...

Спасибо!!!
__________________
Сердце раскололось на тысячи искр, разжигая огонь угасающих глаз, бесконечно смотрящих на холодный свет звезд, не знающих страсти, любви и печали.(c)я
lyuq вне форума  

Опции темы

Ваши права в разделе
Вы НЕ можете создавать новые темы
Вы не можете отвечать в темах.
Вы НЕ можете прикреплять вложения
Вы НЕ можете редактировать свои сообщения

BB код Вкл.
Смайлы Вкл.
[IMG] код Выкл.
HTML код Выкл.

Быстрый переход


Часовой пояс GMT +4, время: 22:03.




Powered by vBulletin® Version 3.8.5
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.