MOJA PASJA - PROGRAMOWANIE
   Dzisiaj jest Czwartek, 24 lipca, 2008r. Ostatnia aktualzacja miała miejsce: 10 grudnia 2006r. Homepage

Programowanie: Artykuły * FAQ * Download * Komponenty * Książki WWW: Artykuły * Narzędzia * Kursy * Darmowe * FAQ * Skrypty * Ksiązki Off-Topic: Aforyzmy * Humor Inne: Forum * Wiki * Liczniki * Linki * Chat * Grafika * Video * Inne



Dynamiczne dołączanie bibliotek dll
Autor: Vnookality    


   Na grupie dyskusyjnej pl.comp.lang.c padło kiedyś pytanie: "... czy mogę jakoś korzystać z bibliotek dll bez tworzenia pliku *.lib i importowania go do projektu?". Rozwiązanie oczywiście jest i jest oczywiście lepsze od importowania *.lib'a. Po pierwsze taka biblioteka jest ładowana do pamięci wraz z głównym modułem programu. Jest to o tyle złe, że gdy mamy zbyt mało pamięci i ogromną ilość modułów *.dll do zaimportowania, to może jej w końcu nie wystarczyć, lub bardzo nieprzyjemnie spowalniać pracę programu i wraz z tym innych aplikacji. Zalet dynamicznego dołączania i zwalniania bibliotek dll to między innymi:

   - lepsze zarządzanie pamięcią. Gdy biblioteka jest nam potrzebna, ładujemy ją, a gdy przestaje - zwalniamy ją po prostu z pamięci.

   - możliwość umieszczania dll'i w dowolnym katalogu programu. Gdybyśmy użyli importowania lib'a biblioteka dll musiałaby znajdować się w głównym katalogu programu, co nie wszystkim może pasować.

   - nie musimy tworzyć wspomnianych plików importowych. To bardzo przyspiesza tworzenie aplikacji i nie wymaga od nas używania innych dodatkowych programów takich jak implib.exe czy też impdef.exe.

   Poniżej pokażę przykład takowej biblioteki. Jak je tworzyć? Trochę inaczej niż biblioteki z plikami importowymi. Tutaj musimy użyć Incremental linker'a. Inaczej naszej biblioteki nie będzie można załadować do pamięci. Oto przykładowy kod takiej biblioteki:

   Unit1.cpp
//---------------------------------------------------------------------------
  #include <vcl.h>
  #pragma hdrstop
//---------------------------------------------------------------------------
  extern "C" __declspec(dllexport) void __stdcall RunThisModule();
//---------------------------------------------------------------------------
  int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*)
  {
     return 1;
  }
//---------------------------------------------------------------------------
  void __stdcall RunThisModule()
  {
     ShowMessage("Hello!");
  }
//---------------------------------------------------------------------------



   Powyższy przykład pokazuje Message'a z napisem "Hello". Jest to najprostsza biblioteka jaka przyszła mi do głowy. No, ale mniejsza z tym. Bibliotekę trzeba (to chyba jasne...) skompilować jako dll. Powiedzmy, że plik biblioteki nazywa się Tutorial.dll. Nazwa dll'a jest bardzo ważna! Sprawdź ją i najlepiej zapamiętaj lub zapisz.

   Teraz czas na program, który wykorzysta naszą bibliotekę. Ten fragment jest najważniejszy. Od niego zależy, czy program po pierwsze załaduje bibliotekę i znajdzie naszą funkcję. Przyjrzyj się poniższemu przykładowi. Potem opiszę cały kod.

   W pliku nagłówkowym (przed deklaracją klasy TForm):

   Unit1.h
  typedef void __stdcall (*PROCRunThisModule)();
  extern "C" void __stdcall RunThisModule();



   W pliku źródłowym:

   Unit1.cpp
  void __fastcall TForm1::Button1Click(TObject *Sender)
  {
     HINSTANCE NaszDLL;
     NaszDLL = LoadLibrary("Tutorial.dll");
     if (NaszDLL == NULL)
     {
        Application->MessageBox("Nie można załadować Biblioteki dll!","Błąd",
        MB_OK | MB_ICONHAND);
     }
     else
     {
        PROCRunThisModule _RunThisModule =
           (PROCRunThisModule)GetProcAddress(NaszDLL, "RunThisModule");
        if (_RunThisModule == NULL)
        {
           Application->MessageBox("Nie znalazłem zdefiniowanej funkcji!","Błąd",
      MB_OK | MB_ICONHAND);         }
        else
        {
           _RunThisModule();
        }
     }
  }



   A teraz opis powyższego kodu. Najpierw tworzymy uchwyt dla naszej biblioteki, czyli w tym przypadku HINSTANCE NaszDLL. Następnie ładujemy bibliotekę dll (LoadLibrary()). Należy zauważyć, że przy ładowaniu dll'a można wprowadzić dowolną ścieżkę dostępu do dll'a. I ważne! Najpierw program próbuje załadować plik o zdefiniowanej nazwie z katalogu głównego programu, a jeżeli jej nie ma, to próbuje znaleźć ją w głównym katalogu Windows'a. Można się o tym przekonać, kasując nasz plik Tutorial.dll z katalogu głównego programu, a kopiując go do katalogu Windows'a. Efekt jest ten sam. Dalej sprawdzamy, czy biblioteka została załadowana. Jeżeli wartość jest równa NULL, zostaje pokazane okno z komunikatem o niepowodzeniu. Jeżeli jest inaczej, program sprawdza czy podana funkcja znajduje się w dll'u. Tak jak wyżej, jeżeli wartość jest równa NULL, zostaje pokazany komunikat. Jeżeli nie byłoby funkcji warunkowej if, program zwróciłby błąd "External exception". Lepiej wygląda jednak błąd zdefiniowany przez nas ;) Jeżeli jednak funkcja występuje, program wykonuje ją.

   Bibliotekę zwalniamy funkcją FreeLibrary("Tutorial.dll"), którą najlepiej umieszczać zaraz po funkcji wywoływanej z dll'a. Jeżeli jest to jednak funkcja wywołująca okno nie modalne, należy pamiętać, że program będzie próbował zwolnić bibliotekę z pamięci mimo iż jest ona używana! W takim wypadku najlepiej deklarację uchwytu naszej biblioteki wstawić tuż pod nazwami plików nagłówkowych, a funkcję FreeLibrary w zdarzeniu OnClose() formy.

   
To by było na tyle. Jeżeli masz jakieś kłopoty, zawsze możesz napisać na mój e-mail: vnookality@poczta.fm lub vnookality@go2.pl. No i... szybkiego kompilowania i zera error'ów :)


   Wasze opinie:
   Średnia ocena: 7.29/10 (34 głosów)
   
   Liczba komentarzy: 10 (pokaż wszystkie)Skomentuj !   


Autor: webster21Data dodania: 2007-06-05
A ja mam takie pytanie. Jak mozna przekazywac zmienne do biblioteki? np: wg artykulu: _RunThisModule("to jest moja wiadomosc");


Autor: _Data dodania: 2007-05-10
D@nior ty jesteś pedałem!


Autor: jerzozwierzData dodania: 2006-05-13
stary uratowałeś mi życie, razem z twoją pracą i pc world komputer pokonałem bestie :) pozdro


Autor: mbData dodania: 2006-04-20
Artykuł ok ale autor zapomniał o zwolnieniu uchwytów...


Autor: nowy :pData dodania: 2006-03-24
Dobry artykuł bo prosty. Przydalby sie tez dla średnio zaawansowanych, np o typach wiadomosci do wyhookowania np WM_KEYBOARD (keylogger :D) albo jak wylapac wiadomosci z neta (chodzi mi o connect, read, write, disconnect itp), moglbym wtedy odczytywac co moje programki knują xD wiecej takich artykulow. plz new article ^^ thx


Autor: author...Data dodania: 2006-03-15
no ja nie uwazam aby ciezko bylo cos o DLLach znalezc, jak potrzebowalem to w mniej niz minute znalazlem. polecam strone www.gamedev.pl - jest glownie dla programistow gier, ale jest takze duzo innych artykulow


Autor: ZibiData dodania: 2006-02-28
ten kod Borland powinien dołączać do plików demonstracyjnych... Podziękowania dla autora za chęć dzielenia się wiedzą...



Stronę przygotował: Kacper Cieśla (comboy). Wszelkie prawa zastrzeżone.
Reklama * Zgłoś błąd * Kontakt * Hosting * O stronie * Sponsoring
Czas generowania strony: 1.138s