Biblioteki dll, debug, init

0

Witam

Mam kilka pytań odnośnie bibliotek dll.
Program macierzysty jest napisany w BDS2006 (Turbo Delphi), natomiast dll'ka w Delphi 4 Standard.

  1. W jaki sposób inicjalizujecie obiekt Application biblioteki dll ? Czy podstawiając Application.Handle := aHandle (gdzie aHandle to uchwyt aplikacji macierzystej), czy podstawiając Application := GetApplication; (gdzie GetApplication to funkcja eksportowa z exe'ca zwracająca obiekt TApplication).

  2. Jak później macie jakieś funkcje eksportowe które wyświetlają modalnie jakieś formatki to jak je tworzycie ? Form1 := TForm1.Create(i tu co?), Application ? , czy przekazujecie jakiegoś aOwner typu TComponent ?

  3. Załóżmy że chcę użyć drugiego sposobu inicjalizowania obiektu application biblioteki dll. Jeśli w BDS napiszę sobie funkcję która mi zwróci Application exe'ca, to czy nie będzie to miało znaczenia że potem podstawiam ją do obiektu Application biblioteki dll ale napisanej w D4 (chodzi mi o to, że przecież te typy mogły się zmienić przez te kilka lat).

  4. Debugowanie dll'ek. Ustawiłem sobie w moim delphi 4 Host Application na tego exec'a który wywołuje moją dll'kę, wyłączyłem optymalizację kodu, powłączałem wszystkie opcje na zakładce Debugging, oraz włączyłem Include Remote Debug Symbols. I żeby było śmiesznie za pierwszym razem zaczęło to działać. Normalnie dawałem F8 i debugowałem krok po kroku moją biblioteczkę. Jednak po zamknięciu Delphi przestało działać :( Macie pomysł co zrobić ? Dodam że na liście modułów (View -> Module list) jak zaznaczę moją dll'kę to nie ma opcji 'Reload System Table'. Jest tylko Break on Load - tyle że to przenosi mnie do okna CPU.

Z góry dziękuje za pomoc.

0

wszystko co tu opiszę jest niezalecane ponieważ korzysta z przekazywania wskaźników rzutowanych na int i jest to kod wysoce podatny na błędy. Poza tym jeśli nigdzie się nie pomylisz to masz prawie 100% szansę, że będzie działał OK :p. Lepiej takie rzeczy robić w bplach ale tu i exe i bpl MUSZĄ być z tej samej wersji delphi :(

krótki wstęp
cały problem jest z tym, że Application oraz Screen (screen też musisz podmienić jeśli chcesz formy MDIChild najprawdopodobniej dla modalnego też trzeba) są różne dla aplikacji i dllki. Aby to zmienić i nie dostać AV przy zamykaniu musisz

  1. po załadowaniu DLLki wywołać metodę z niej, do której przakazujesz Application i Screen zrzutowany na Integer
  2. w dllce ta metoda musi
    a) zapamiętać w jakiejś zmiennej własny Application i Screen
    b) podmienić na ten uzyskany z execka
  3. teraz wszystkie okna tworzone w dllce powinny się zachowywać jakby były tworzone w execku
  4. WAŻNE! zanim wyładujesz dllkę z pamięci musisz w niej przywrócić oryginalny Screen i Application
    a) albo przez napisanie dodatkowej metody, którą wywołasz z exe
    b) albo przez DLLProc

a teraz odpowiedzi na pytania :p

  1. patrz wyżej
  2. TForm1.Create(nil) - mam taką zasadę, że co sam tworzę sam niszczę. AOwner jest tylko po to, że jak jest niszczony to najpierw niszczy wszystkie swoje "własności" - nic więcej
  3. Takie rzeczy się nie zmieniają - spokojnie możesz podmienić jedno pod drugie
  4. debugowanie dllek zawsze było problemem w Delphi, być może w D2k6 coś się poprawiło ale np. w D7 trzeba było mieć dużo szczęścia, żeby to zaskoczyło więc tu Ci nie pomogę
0
Misiekd napisał(a)

...

  1. po załadowaniu DLLki wywołać metodę z niej, do której przakazujesz Application i Screen zrzutowany na Integer
  2. w dllce ta metoda musi
    a) zapamiętać w jakiejś zmiennej własny Application i Screen
    b) podmienić na ten uzyskany z execka
  3. teraz wszystkie okna tworzone w dllce powinny się zachowywać jakby były tworzone w execku
  4. WAŻNE! zanim wyładujesz dllkę z pamięci musisz w niej przywrócić oryginalny Screen i Application
    a) albo przez napisanie dodatkowej metody, którą wywołasz z exe
    b) albo przez DLLProc

W exe'cu (konkretnie w dpr'ce) zrobiłem:

function GetApplication : Integer;
begin
Result := Integer(Application);
end;

function GetScreen : Integer;
begin
Result := Integer(Screen);
end;

i dodałem obie do klauzuli exports.

W dll'kach w DllProc przy DLL_PROCESS_ATTACH wywołuję taki kod:

begin
If not Assigned(OldApp) then
Begin
GetApp := GetProcAddress( GetModuleHandle(PChar(Application.ExeName)), 'GetApplication');
GetScr := GetProcAddress( GetModuleHandle(PChar(Application.ExeName)), 'GetScreen');

    If Assigned(GetApp) then
          	Application := TApplication(GetApp());
    If Assigned(GetScr) then
          	Screen := TScreen(GetScr());
End;

end;

(usunąłem kilka sprawdzeń żeby nie unieczytelniać, tak czy siak debugowałem i ta podmianka robi się bez problemu, OldApp i OldScr to zmienne globalne inicjowane na początku na nil). Jednak rezultat jest taki sam jak na początku kiedy funkcje z exe'ca zwracały mi wprost obiekt TApplication: przy tworzeniu formatki (obojętnie czy f := TForm1.Create(nil) czy f := TForm1.Create(Application) dostaję AV. Oczywiście przy zwalnianiu podmieniam z powrotem ale to i tak nie ma tutaj znaczenia. Moje przypuszczenia są takie, że być może te typy nie są w 100% zgodne, może w BDS np obiekt TApplication ma jakieś dodatkowe pola, co w połączeniu z rzutowaniem (bo tak czy siak czy Twój sposób czy mój to to rzutowanie gdzieś występuje) daje AV. Znamienne jest to, że jak zrobiłem funkcję eksportową w exe'cu która zwraca uchwyt Application.Handle i w dll'ce podstawiłem ten uchwyt do uchwytu obiektu Application dll'ki to wszystko działa. Jest jeszcze jedna znamienna rzecz - przy tej operacji też chciałem zapamiętać stary uchwyt żeby go potem przywrócić, lecz on jest zawsze = 0 ??

No i co tu na to poradzić ? Chyba generalnie wymiana międzyplatformowa (D4Std <-> BDS) obiektów nie jest najlepszym pomysłem szczególnie gdy są to obiekty systemowe. Chociaż np mam w dll'ce funkcje która przetwarza wyjątki (Exception) i jak do niej przekazuje wyjątek z exe'ca to jest ok : )

0

a stdcall :>

btw
tworzyłem formy z dll nie raz i nie było AV

0
Misiekd napisał(a)

a stdcall :>

Stdcall nic nie zmieni, zresztą przy funkcjach bez parametrów ... Poza tym oba moduły są w Delphi, więc tu i tu jest pewnie przyjmowane register.

Misiekd napisał(a)

btw
tworzyłem formy z dll nie raz i nie było AV

Ja nie twierdzę że mi coś źle mówisz, albo że nie robiłeś formatek w dll. Sam ich robiłem dużo w robocie. Pytanie czy robiłeś formatki z jednej wersji delphi dla drugiej ? Zresztą ta sytuacja o której pisze - to jak i exe'ca i dll'ke skompiluje w BDS2006 to działa aż miło - jednak sytuacja wymaga tego żebym część softu napisał w D4 a część w BDS [w D4Std mogę robić własne komponenty, a w BDS Explorer mogę używać SQL'owych BD - a ja potrzebuję obu rzeczy naraz, dodam że interesują mnie tylko legalne rozwiązania :)]

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