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
- Rejestracja:około 20 lat
- Ostatnio:ponad 11 lat
- Postów:55
- Rejestracja:prawie 17 lat
- Ostatnio:około 16 lat
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
- zadeklarować funkcję która ma w definicji wpisane że siedzi w jakiejś dll'ce
- 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 =)
- Rejestracja:około 20 lat
- Ostatnio:ponad 11 lat
- Postów:55
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
- Rejestracja:prawie 17 lat
- Ostatnio:około 16 lat
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 ?
- Rejestracja:około 20 lat
- Ostatnio:ponad 11 lat
- Postów:55
1 zrobilem tak jak mowisz zamienilem tan kod i gdy ta procedurka ma byc uruchomiona wywala error aplication cos tam 000000
....
- 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
- Rejestracja:prawie 17 lat
- Ostatnio:około 16 lat
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ć =)
- Rejestracja:około 20 lat
- Ostatnio:ponad 11 lat
- Postów:55
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...
- Rejestracja:prawie 17 lat
- Ostatnio:około 16 lat
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
- Rejestracja:prawie 17 lat
- Ostatnio:około 16 lat
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ć =)
Zarejestruj się i dołącz do największej społeczności programistów w Polsce.
Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.