tabele z unit1 w dll

0

Witam co trzeba zrobić żeby w funkcji w DLL można było używać Tabel z unit1.
bo jak pisze procedurę w dll np. żeby wyświetliła messageboxa z jakąś wartością z tabeli to nic nie wyświetla... okno sie wyświetli ale puste...
i nie wiem jak to mam zrobić aha i zapisać do tabeli tez sie nie da niby zapisuje ale tabela jest pusta... bo żaden error przy kompilacji ani w trakcie działania programu nie wyskakuje

0

konkretów więcej by się przydało =)

z racji braku informacji nic o tablicy ci nie powiem ale na pewno ci chodzi o " wycieki pamięci z dll'ki "

a więc tak: są dwa główne sposoby użycia jakiejś metody z dll'ki

  1. zadeklarować funkcję która ma w definicji wpisane że siedzi w jakiejś dll'ce
  2. wczytać dll'kę do pamięci, zgarnąć jej handler, i używając go przypisać do odpowiednich zmiennych metody z dll'ki, pod koniec zwolnic ją

teraz opis twojego problemu ( o ile dobrze Cię zrozumiałem )

możliwe iż używasz sposobu pierwszego, w tym przypadku 'dll'ka jest ładowana tylko na czas wykonania metody i wtedy zwalniana, więc za każdym wywołaniem jakiejś metody tablica jest tworzona od nowa, więc jest pusta

przy przechowywaniu danych w dll'ce używaj sposobu drugiego gdyż wtedy dll'ka jest ładowana przy pierwszym opisanym prze ze mnie kroku i zwalniana przy ostatnim, więc tablica jest stale w pamięci =)

poczytaj w helpie o funkcji LoadLibrary
jej używa się w drugim sposobie =)

0

kurcze nize zabardzo cie rozumie ...

napisze to inaczej...
to tak w unicie1 mam deklaracje tej tabelki

Type TPlayer = record
  imie : string[15];
  pole : integer;
  kasa : integer;

var  player1 : TPlayer;   //pole na ktorym stoi player1
 

a procedureke z dll wywoluje tak:

  Procedure oplata_pos(Form1:TForm1); stdcall external 'Data1.dll' name 'oplata_pos';

a w pliku dll mam tak:

Procedure oplata_pos(Form1:TForm1); stdcall;
 Begin
        player1.kasa := player1.kasa - pole[player1.pole].dom_postoj_0;
         Application.MessageBox(PAnsiChar('Płacisz za postuj na ' + pole[player1.pole].nazwa + ' ' + inttostr(pole[player1.pole].dom_postoj_0) + ' $'), 'Bank',  MB_OK + MB_ICONINFORMATION);
      
 End;

w tabelce pole sa powprowadzane rozne wartosci integer ...sa tam na 100%:P

no ale jak sie wyswietli ten messagebox to mi sie pokauje taki tekst:

Płacisz za postujna $

nio:P

0
Procedure oplata_pos(Form1:TForm1); stdcall external 'Data1.dll' name 'oplata_pos';

i w tym masz problem =)
to jest ten pierwszy sposób, ładowanie dll'ki do pamięci na czas wykonania metody
po wykonaniu metody dll'ka jest zwalniana z pamięci więc tabelka też znika =)

najpierw deklaracja zmiennej na procedurę i zmiennych pomocniczych, dobrze by było by były globalne dla danego modułu ( ten blok var gdzie jest Form1:TForm1; )


var
  Oplata_pos : procedure ( Form1:TForm1);
  handler:cardinal;

a tu przygotowanie do użycia ( np w OnCreate formy )


  handler:=LoadLibrary('Data1.dll'); // funkcja WinApi zwracająca "uchwyt" dll'ki

  @Oplata_pos:=GetProcAddress(handler,'Oplata_pos'); 
  // funkcja wyszukująca " uchwyt " metody o podanej nazwie ( drugi parametr )
  //  w dll'ce do której podajemy "uchwyt" ( pierwszy parametr )

na zakończenie


  FreeLibrary(handler); // zwalniamy dll'kę z użycia

użycie


  Oplata_pos(Form1); // będzie działać dopiero po inicjalizacji ( to z LoadLibrary )

a teraz pytanie za 100$
po co wysyłasz zmienną z Form1 do dll'ki ?
jeśli jest ci to naprawdę konieczne to przerób to na wysyłanie wskaźnika, jako że forma przechowuje dosyć dużo danych i takie wysyłanie nie jest dla komputera przyjemne =)

przy wielkiej ilości metod w dll'ce dobrze jest ją wyposażyć w metodę która poda programowi uchwyty do wszystkich jej metod, co znacznie umili używanie tej dll'ki

w razie problemów ze zrozumieniem użyje do tego porównania

zapewne wiesz że jak zadeklarujesz jakąś zmienną w procedurze OnClick jakiegoś przycisku to jest ona dostępna tylko dla danego przycisku, i przechowuje dane tylko na czas " kliknięcia " ( na czas wykonania tej procedury )

natomiast zmienna Form1 jako iż jest globalna dla całego modułu, jest w pamięci dopóki moduł jest w pamięci i z każdego miejsca kodu możesz się do niej dostać w dowolnym momencie

to pierwsze jest podobne do danych w dll'ce wywoływanej metodą pierwszą a drugie do dll'ki wywoływanej metodą drugą

uhm... wpadło mi do głowy głupie pytanie.... czy ten moduł jest w dll'ce czy w programie ?

0

1 zrobilem tak jak mowisz zamienilem tan kod i gdy ta procedurka ma byc uruchomiona wywala error aplication cos tam 000000
....

  1. nie rozumiem dlaczego tabelka znika?? ona jest zadeklarowana w programie a nie w dll'ce dllka ma za zadanie przypisac do jednego rekordu z tej tablicy jakas wartosc...

3 nie wiem czy ty zle rozumiesz czy ja ;) heh

0

obaj..... już wiem dlaczego jako argument funkcji dawałeś Form1 .... próbowałeś przerzucić tą tabelkę ( tak naprawdę to rekord a nie tabelka ) z programu do dll'ki jako argumentu używając Formę, lecz to ci nie prześle tabelki tak jakbyś chciał z wielu powodów

skoro już chyba cię zrozumiałem zrób to w ten sposób

w programie deklaracja procedury

Procedure oplata_pos(Pplayer:Pointer); stdcall external 'Data1.dll' name 'oplata_pos';

w dll'ce i w programie deklaracja typów


Type TPlayer = record
  imie : string[15];
  pole : integer;
  kasa : integer;

w dll'ce opis procedury


Procedure oplata_pos(Pplayer:Pointer); stdcall;
var
  Player:^TPlayer;
Begin

  Player:=Pplayer;
   
  //i tu to twoje pokazywanie wiadomości np:
  ShowMessage(Player.imie);
     
End;

wywołanie procedury przez program


  Oplata_pos( Addr(player1) );

będzie to działać tak:

program wrzuca do pamięci rekord TPlayer i pozwala ci dobrać się do niego przez zmienną player1
funkcja Addr() odczytuje wskaźnik ( Pointer ) do zmiennej player1
wskaźnik to adres komórki ( lub komórek ) pamięci gdzie są dane jakiejś zmiennej ( tutaj player1 )
jako argument procedury podajemy ten wskaźnik
dll'ka przypisuje ten wskaźnik do zmiennej wskaźnikowej Player:^TPlayer więc zmienna Player w dll'ce jak i zmienna player1 odnoszą się do TYCH SAMYCH komórek pamięci, więc tą samą zmienną możesz odczytywać i zapisywać tak i z programu jak i dll'ki, więc co zmienisz w dll'ce będzie widoczne dla programu, a co zmienisz w programie będzie widoczne w dll'ce
dodatkowym plusem jest przesyłanie pomiędzy programem a dll'ką mniejszych ilości danych
bo Pointer zajmuje w pamięci ledwie parę bitów ( jedna ósma bajta ) a typ TPlayer zajmuje:

imie:string[15] - 15 razy jeden bajt co daje 15 bajtów
pole:integer - 32 bity czyli 4 bajty
kasa:integer - 32 bity czyli 4 bajty

razem 23 bajty, to jest tyle co 23 znaki w pliku tekstowym, ale i tak dużo zaoszczędzamy =)

to powinno zadziałać =)

0

tak dzieki wielkie to dziala ladnie pieknie jak mam 1 zmienna ale jak wysle juz jakas tablice... o typie TPole... to mi wywala blad...a jak zamiast pointer dam array of Tpole to mi pisze incompatible type dynamic of array czy cos takiego...bo oprocz trakiej zmiennej to jeszcze musze tablice wyslacdo tej procedurki w dll...

0

nie działa ci przekazywanie wskaźnika do całej zmiennej?
zaproponowałem to dlatego że dynamicznych tablic lepiej nie przesyłać pomiędzy dll'ką a programem, z tego samego powodu dla którego zamiast stringa wysyłasz PChar ( PChar to po prostu wskaźnik do string'a )

próbowałeś przesłać wskaźnik do tej tablicy? zaraz sprawdzę jak się to sprawuję i dopisze coś=)

mi wszystko hula ładnie, przesyłałem całą dynamiczną tablicę, ze wskaźnikiem do niej jeszcze muszę się pobawić

deklarujesz typ komórki oraz tablicę dynamiczną

type Tcell

    name:string;
    number:integer;

  end;

var
  players:array of Tcell;

teraz deklaracja procedury z dll'ki

procedure Something(list:array of Tcell); external 'data.dll';

dostęp do listy jest prosty


procedure Something(list:array of Tcell);
begin

  ShowMessage( IntToStr( Length( list ) ) );
  ShowMessage( list[0].name );

  // i tak dalej

end;

w ten sposób nie będziesz mógł zapisywać danych w tablicy z poziomu dll'ki ( dll'ka dostaje kopie tablicy, a nie jak w przypadku użycia Pointer'ów tą samą )

a, i typ Tcell musi być oczywiście zdefiniowany w programie i w dll'ce =)

jak wykombinuje w czym mam problem to napisze jak rzucić Pointerem do tablicy, bo podczas działania programu wszystko działa, błąd jest dopiero przy wyłączaniu =) dziiiiwnneee

0

no właśnie nie działa a jest jakiś wskaźnik do tabel ... nie wiem co by z tym zrobić...
gdyby to miała być jakaś pojedyncza funkcja to olałbym to no ale to praktycznie każda funkcja z tej tabelki będzie korzystać ...

0

no ja zrobiłem tak:


type Tcosik = record

    List:array of Tcell;

  end;

var
  cosik:Tcosik

i mamy dynamiczną tablicę rekordów wsadzoną do jednej zmiennej

funkcją Addr() bierzemy jego Pointer i przesyłamy do dll'ki

w dll'ce mając te same typy w procedurze definiujemy zmienną wskaźnikową


procedure blablabla
var
  cosik:^Tcosik;
begin
  
  blablabla

end;

i wszystko ładnie działa, da się zmieniać długość, edytować wartości, co zmieni dll'ka widzi też program itd

ale problem jest przy zamykaniu programu że wypluwa błędy ( Invalid pointer operation ), próbuję temu jakoś zaradzić ale coś mi nie wychodzi =)

Edit

metodą prób i błędów wyciągnąłem co robi błąd, okazało się że występuje on tylko po dokonaniu zmian we wspólnych danych przez dll'kę =)
na to też spróbuję coś poradzić =)
ale już jutro bo trzeba iść spać =)

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