Problem z ładowaniem własnej biblioteki .dll

0

Mam taki plik Quotations.dll:

library Quotations;

uses
  ShareMem, Windows, Messages;

{$R *.res}

const
  WM_PROCESSEND = WM_USER + 1100;
  AQuotations: array[1..65] of ShortString =
   ( {Tutaj cytaty} )

function SelectQuote(i: Integer): ShortString; stdcall;
begin
 Randomize;
 while i = 0 do
  i:= Random(65);
 Result:= AQuotations[i];
end;

procedure DLL_Proc(Reason : Integer);
begin
 if Reason = DLL_PROCESS_DETACH then
  SendMessage(FindWindow('TMainForm', nil), WM_PROCESSEND, 0, 0);
end;

exports
  SelectQuote name 'SelectQuote';

begin
 DLLProc := @DLL_Proc;
end.

i w programie dwie procedury:

const WM_PROCESSEND = WM_USER + 1100; 

  private
    { Private declarations }
    procedure WMProcessEnd(var Msg : TMessage); message WM_PROCESSEND;
    procedure Quotations_DLL;

procedure TAktualizuj.WMProcessEnd(var Msg : TMessage);
begin
 MainForm.Quote.Caption:= 'Cytat dnia:  ' + Quote;
end;

procedure TAktualizuj.Quotations_DLL;
var DLL: THandle;
    SelectQuote: function(i: Integer): ShortString;
begin
 DLL := LoadLibrary('Quotations.dll');
 try
  @SelectQuote:= GetProcAddress(DLL, 'SelectQuote');
  if @SelectQuote = nil then
   raise Exception.Create('Nie można wczytać cytatów!');
  Quote:= SelectQuote(0);
 finally
  FreeLibrary(DLL);
 end;
end;

i gdzieś w dalszym kodzie ;p

 Quotations_DLL;

Po wykonaniu przez program procedury Quotations_DLL; wyświetla się błąd Debugger Fault Notification:
Project ..\Project1.exe raised too many consecutive exceptions: 'access violation at 0x00000000: read of address 0x00000000'. Process Stopped. Use Step or Run to continue.

i okno CPU, w którym:

00000000 ????
00000001 ????
itd.

Proszę o pomoc w naprawieniu błędu/ów, które to powodują.

0

deklarujesz prekazywanie parametrów przez stdcall, wywołujesz przekazując parametry przez pascal. musi być to samo po obu stronach.

0

Dodałem stdcall do:

SelectQuote: function(i: Integer): ShortString; stdcall;

Tym razem aplikacja nie zawiesza się, ale wciąż występuje błąd:

Instrukcja spod "0x00000000" odwołuje się do pamięci pod adresem "0x00000000". Pamięć nie może być "read".
Kliknij przycisk OK, aby przerwać działanie aplikacji

@Edit

Zmieniłem kod na:

uses ShareMem...

const WM_PROCESSEND = WM_USER + 1100;

  private
    { Private declarations }
    procedure WMProcessEnd(var Msg : TMessage); message WM_PROCESSEND;
    procedure Quotations_DLL;

type
 TSelectQuote = function (i: Integer): ShortString; stdcall;

procedure TAktualizuj.WMProcessEnd(var Msg : TMessage);
begin
 MainForm.Quote.Caption:= 'Cytat dnia:  ' + Quote;
end;

procedure TAktualizuj.Quotations_DLL;
var DLL: THandle;
    SelectQuote: TSelectQuote;
begin
 DLL := LoadLibrary('Quotations.dll');
 try
  @SelectQuote:= GetProcAddress(DLL, 'SelectQuote');
  if @SelectQuote = nil then
   raise Exception.Create('Nie można wczytać cytatów!')
  else
   Quote:= SelectQuote(0);
 finally
  FreeLibrary(DLL);
 end;
end;

działa, tylko gdy wyłączam program to wyskakuje Invalid pointer operation.

0

upewnij się, że Quote zawiera kopię, a nie referencję do tego, co SelectQuote zwróciło.

poza tym imho troche dziwnie obsługujesz ładowani/wyładowanie biblioteki. załaduj ją raz na początku działania programu, a w finalization raz wyładuj.

0

co do stringów i unitu ShareMem wiele ne mam do powiedzenia gdyż nie korzystam z tego, ale być może najpierw trzeba określić niezbędną długość przyszłego stringa. Najłatwiej Tobie bedzie przekazywać wynik funkcji nie jako ShortString a PChar - bedziesz miał krótszy plik chociażby, albo można ostatecznie "na desperata" jakby Ci wyjsc nie chcialo atomami globalnymi to zrobić...
na proponuje potestowanie tego z PCharami

0

przy uzywaniu PChar nie musisz używać modułu ShareMem, jest to nawet zalecane (jak informuje o tym delphi w swym komentarzu przy tworzeniu dll)

0

Dzięki wszystkim za wskazanie właściwej drogi. Po zmienieniu ShortString'ów na PChar'y oraz odjęciu biblioteki ShareMem, kod dll'ka schudł o 37,5% (32 Kb > 20 Kb), a błąd już nie występuje (dopóki używałem ShareMem występował).

1 użytkowników online, w tym zalogowanych: 0, gości: 1