Lista jednokierunkowa w DLL i przekazywanie wskaźnika.

0

Zostanę znienawidzony za swoją niekompetencję na forum, jednak zmuszony jestem ponownie prosić o pomoc, lub podpowiedź w związku z projektem z list jednokierunkowych w bibliotece DLL.
Jako, że mimo pokonania magicznego błędu wcześniej nadal miałem problemy z projektem, postanowiłem napisać go od nowa i testować wszystkie małe fragmenty po kolei. Stworzyłem więc nową bibliotekę DLL zawierającą tylko procedury "Dodaj rekord do listy na pierwszym miejscu"(wiem, mało elegancko, ale chcę zacząć od czegoś gdzie w procedurze nie będzie błędu ze względu na prostotę i później to poprawić mając wersję podstawową, która na pewno działa) oraz "Usuń pierwszy rekord z listy".
W nowym unicie stworzyłem pojedynczy przycisk wywołujący trzy razy funkcję dodającą i dwukrotnie usuwającą, jednak przy drugim (i kolejnych) uruchomieniu usuwania procedura usuwająca zachowuje się jakby wskaźnik na listę wskazywał nil(wywołuje okienko które miało się pokazywać przy próbie usunięcia elementu którego nie ma), czyli jakby moja zmienna first nigdy nie zmieniła swojej wartości.
Podejrzewam, że nie rozumiem jak owy first jest przekazywany między unitem, a DLL.
Serdecznie dziękuję za wszelkie podpowiedzi!
A i tak, wszystko kompiluje bez żadnych błędów.
DLLka

library ProjectDLL;

uses
  System.SysUtils,
  System.Classes,
  Vcl.Dialogs,
  Baza;

procedure Dodajdolisty(elem:Tdane);stdcall;
  var t:wsk;
begin
  try
    if first=nil then t:=nil else t:=first^.next;
    new(first);
    first^.dane:=elem;
    first^.next:=t;
  except
    showmessage('Nieudane dołączanie elementu do listy.');
  end;
end;

procedure Usunpierwszyzlisty();stdcall;
  var t:wsk;
begin
  try
    if first=nil then showmessage('Brak elementu do usunięcia.')
    else
    begin
      t:=first;
      first:=first^.next;
      dispose(t);
    end;
  except
    showmessage('Nieudane usunięcie elementu.');
  end;
end;

exports
Dodajdolisty index 1,
Usunpierwszyzlisty index 2;

begin
end.

I główny Unit

unit Baza;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
type
  TDane=record
    ocena:byte;
  end;
  wsk=^lista;
  lista=record
    dane:tdane;
    next:wsk;
  end;
var first:wsk; DLL:Thandle;
Dodaj:procedure(rekord:tdane);stdcall;
Usun:procedure();stdcall;

implementation
{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var elem:tdane;
begin
  DLL:=loadlibrary('DLL');
  try
    first:=nil;
    @Dodaj:=getprocaddress(DLL,pchar(1));
    @Usun:=getprocaddress(DLL,pchar(2));
    if (@Dodaj=nil)or(@Usun=nil) then raise Exception.Create('Nie znaleziono procedury w bibliotece.');
    elem.ocena:=5;
    Dodaj(elem);
    elem.ocena:=7;
    Dodaj(elem);
    elem.ocena:=9;
    Dodaj(elem);
    Usun();
    Usun();
  finally
    freelibrary(DLL);
  end;
end;

end.
1
DeXo napisał(a):

Zostanę znienawidzony za swoją niekompetencję na forum ...
Za niekompetencję raczej nie, zaś za ignorowanie odpowiedzi to jakoś się nie chcę mi już odpowiadać: http://4programmers.net/Forum/1208059

0

Nie zignorowałem odpowiedzi, zastosowałem się do "pierwszego z dwóch" (a przynajmniej tak myślałem). Wiem, że pominąłem uwagę o try except, jednak w sumie z przyzwyczajenia już to zostawiłem. Z tamtych odpowiedzi wywnioskowałem, że obecny sposób powinien być ok, ponieważ first będzie przekazywany przez referencję, więc zamiast funkcji napisałem procedurę, bo nie czułem potrzeby by coś zwracało.
Jednak "w praniu" wyszło mi, że coś z przekazywaniem wartości tego first'a jest nie tak i nie potrafię zrozumieć dlaczego (w moim odczuciu kolejne elementy nadpisują pierwszy zamiast się przed niego "wcisnąć", więc usunięcie pierwszego powoduje usunięcie jedynego elementu, jednak znając siebie, moje rozumowanie jest błędne).
W powyższym wypadku jest on zmienną globalną Unitu, który dodałem w Uses DLLki, ponieważ myślałem, że w ten sposób będzie on zawsze dostępny (i w Unicie i DLLce), a jego zmiana w którymkolwiek z nich sprawi, że będzie to prawidłowo działało, jednak jak widać myliłem się.
Dlatego, przepraszam za natręctwo, jednak nadal nie potrafię rozwiązać swojego problemu.
_13th_Dragon już powinieneś dostać medal za wytrwałość.

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