Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Sheddex

unregistriert

1

09.08.2006, 16:57

Dynamic Link Libraries erstellen (*.dll)

Dynamic Link Libraries erstellen

Dynamic Link Libraries mit Visual Studio erstellen

Was ist eine Dynamic Link Library?
Gesehen hat sie sicher jeder schon einmal: Die Dateien, deren Icon aus zwei Zahnrädern besteht und deren Endung *.dll lautet. Bei einer solchen Datei handelt es sich um eine Dynamic Link Library, kurz einfach DLL. Im Gegensatz zu normalen Bibliotheken wird eine DLL genau ein einziges Mal in den Speicher geladen, selbst wenn sie von mehreren Programmen auf einmal benötigt wird. Wird ein Programm gestartet welches eine DLL benötigt wird diese in den Speicher geladen und der sogenannte Referenzzähler auf 1 gesetzt. Jedes weitere Programm welches die DLL verwendet erhöht den Zähler um 1, lässt die DLL jedoch nicht erneut in den Speicher laden. Der Referenzzähler stellt also die Anzahl der Programme die eine bestimmte DLL verwenden dar. Wird ein solches Programm beendet wird auch der Referenzzähler um 1 verringer. Die DLL wird aus dem Speicher geladen sobald der Zähler 0 erreicht und damit kein Programm übrig ist, welches Gebrauch von der DLL macht.
DLLs machen außerdem durch Plugins erweiterbare Programme möglich. So kann zum Beispiel ein Browser plötzlich ein Wörterbuch beinhalten, welches durch ein Plugin in Form einer DLL hinzugefügt wurde. Um so etwas zu realisieren muss die DLL dynamisch geladen werden. Dies wird in diesem Tutorial jedoch nicht das Thema sein: Hier geht es lediglich um das statische Laden.

Projekteinrichtung
Ich selbst verwende Visual Studio 2005 Standard. Der Vorgang sollte jedoch bei allen 2005er und 2008er Versionen der Gleiche sein. Wer keine Visual Studio besitzt kann einen Blick auf die kostenlose und sehr gute Visual C++ 2008 Express Edition werfen.
Zuerst erstellt man ein DLL Projekt. Als Vorlage wird hierzu ein Win32-Projekt verwendet. Nach der Eingabe des Namens, welcher zum Beispiel "DLL" lauten kann, wird als Anwendungstyp "DLL" gewählt und ein Haken bei "Leeres Projekt" gesetzt. Nachdem noch eine Headerdatei (dll.h) und C++-Datei (dll.cpp) hinzugefügt wurden ist das Projekt fertig eingerichtet.

Die DllMain
Die Funktion namens "DllMain" wird aufgerufen sobald ein Programm gestartet wird welches die DLL verwenden will. Sie wird ebenfalls aufgerufen wenn ein solches Programm beendet wird. Hier das Grundgerüst der Funktion:

C-/C++-Quelltext

1
2
3
4
BOOL WINAPI DllMain(HINSTANCE handle, DWORD reason, LPVOID reserved)
{
  return TRUE;
}


Der erste Parameter der Funktion ist, wie der Name schon sagt, das Handle der DLL. Benötigt man es kann man es hier "abfangen". Der zweite Parameter ist der Grund, aus welchem die Funktion aufgerufen wurde. DLL_PROCESS_ATTACH bedeutet beispielsweise, dass ein neuer die DLL verwendender Prozess gestartet wurde wohingegen DLL_PROCESS_DETACH genau das Gegenteil, nämlich dass ein solcher beendet wurde bedeutet. Der letzte Parameter sagt aus, ob die DLL dynamisch oder statisch geladen wurde. Wurde sie dynamisch geladen ist er 0, wurde sie statisch geladen ist er nicht 0.

Exportieren und importieren
Jede Klasse, Funktion und Variable muss zur späteren Verwendung in die DLL exportiert werden. Dies geschieht mittels "__declspec(dllexport) ". Die Export-Anweisung steht noch vor dem eigentlichen Namen der Klasse, Funktion oder Variable.

C-/C++-Quelltext

1
2
3
class __declspec(dllexport) test_class;
void __declspec(dllexport) test_function();
int __declspec(dllexport) test_variable;


Das Exportierte muss später natürlich auch wieder importiert werden. Da sich niemand die unnötige Mühe machen will zusätzliche Headerdateien nur für den Import zu erstellen verwendet man hier üblicherweise ein Makro (hier "DLL" genannt) welches beim Erstellen des DLL Projektes zu "__declspec(dllexport) " wird und beim Importieren zu "__declspec(dllimport) ", der Import-Anweisung. Dieses Makro wird in dll.h vorzufinden sein.

C-/C++-Quelltext

1
2
3
4
5
#ifdef DLL_EXPORTS
#define DLL __declspec(dllexport)
#else
#define DLL __declspec(dllimport)
#endif


Wird ein DLL-Projekt erstellt definiert Visual Studio ein Makro welches den Namen des Projektes (ohne Sonderzeichen sofern vorhanden) gefolgt von "_EXPORTS" trägt. Ist dieses gesetzt wird hier exportiert, ist es nicht gesetzt importiert. Da es später beim Verwenden der DLL selbstverständlich nicht gesetzt ist wird alles zuvor Exportierte importiert.

Die Testfunktion
Die Testfunktion wird ist natürlich sehr simpel aufgebaut: Sie erzeugt lediglich eine Message Box.
In dll.h ist sie wie folgt deklariert:

C-/C++-Quelltext

1
void DLL message();


Definiert ist sie in dll.cpp folgendermaßen:

C-/C++-Quelltext

1
2
3
4
void message()
{
   MessageBoxW(0, L"Dies ist eine Nachricht", L"Information", MB_ICONINFORMATION | MB_OK);
}


Das "DLL" muss also wie man hier sieht nur in der Headerdatei stehen. Um die Funktion "MessageBoxW" verwenden zu können muss selbstverständlich zuvor "windows.h" inkludiert worden sein.

Anwendung
Nach der Erstellung des Projektes erhält man zwei Dateien: Die DLL-Tutorial.dll und die dll.lib. Diese beiden Dateien verschiebt man nun mitsamt der dll.h in den Ordner eines Testprojektes. Alternativ kann man für dieses Projekt in den Optionen unter "Projekte und Projektmappen" die Pfade zur Header- und zur Bibliotheksdatei bekannt geben. Die DLL muss sich jedoch direkt im Ordner des Testprogrammes befinden. Damit man die DLL nicht ständig vom DLL-Projekt in den Hauptprojekt Ordner verschieben muss besteht die Möglichkeit die beiden Projekte in einer Projektmappe zu vereinen. Dadurch werden DLL und Exe im gleichen Ordner erstellt.
Der Code einer Beispielanwendung kann nun folgendermaßen aussehen:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
#include "dll.h"

#pragma comment (lib, "dll.lib")

int WINAPI WinMain(HINSTANCE instance, HINSTANCE prev_instance,
                   char* command_line, int show_command)
{
   message();
   return 0;
}


Download der Projektedateien

$nooc

Alter Hase

Beiträge: 873

Wohnort: Österreich / Kärnten

Beruf: Schüler

  • Private Nachricht senden

2

09.08.2006, 20:24

sieht recht ausführlich aus :)
ist das wegen mir entstanden? *geschmeicheltfühl* ;)


sobald ich wieder zu hause bin werde ich mich da ran machen *hihi*
Am Anfang der Weisheit steht die eigene Erkenntnis, dass man selbst nichts weiß! - Sokrates

Sheddex

unregistriert

3

09.08.2006, 20:27

Mmh, jo ist glaub' ich wegen dir entstanden ;)
Aber ich wollte ja eh was schreiben, mir ist aber leider nichts einfallen, was sich dann geändert hat^^

$nooc

Alter Hase

Beiträge: 873

Wohnort: Österreich / Kärnten

Beruf: Schüler

  • Private Nachricht senden

4

09.08.2006, 20:31

:D also war das mehr ein 'mir is fad'-akt als ein 'ich helf dir mal'-akt

:P


ne ^^
sobald ich zeit hab knie ich mich dahinter *hehe*
Am Anfang der Weisheit steht die eigene Erkenntnis, dass man selbst nichts weiß! - Sokrates

Anonymous

unregistriert

5

09.08.2006, 20:46

Header Guards fehlen immer noch :badgrin:

Sheddex

unregistriert

6

09.08.2006, 20:46

Blödsinn ;)

Es hat mich immerhin viel Zeit gekostet in der ich meine DirectInput Klasse hätte fertigstellen können ;)

@DarkRaider: VERDAMMT!!! Ich hab' das Teil ja generalüberholt und hab' gedacht: Jetzt kommen die rein... und ich hab's vergessen xD

EDIT: Sie sind da ;)

CW_Kovok

Alter Hase

Beiträge: 836

Wohnort: nähe Bonn

Beruf: Schüler

  • Private Nachricht senden

7

09.08.2006, 20:55

es wäre auch noch schön zu beschreiben, wie man nur die benötigten Funktionen aus den dlls läd
Was es alles gibt, das ich nich brauche - Aristoteles

Sheddex

unregistriert

8

09.08.2006, 21:50

Eigentlich versteh ich den Sinn davon nicht, man braucht doch unbedingt alle Funktionen :badgrin:
Und außerdem hab ich das noch nie gemacht ;)

CW_Kovok

Alter Hase

Beiträge: 836

Wohnort: nähe Bonn

Beruf: Schüler

  • Private Nachricht senden

9

09.08.2006, 22:05

klar ich lade auch 700 kb lib für eine funktion...
Was es alles gibt, das ich nich brauche - Aristoteles

Sheddex

unregistriert

10

09.08.2006, 22:12

Naja, wer's braucht soll auf German Game Dev gehen ;)

Werbeanzeige