Neben den beiden eigentlich genutzten Funktionen ist noch die Funktion DllMain() enthalten, die beim Laden und Entladen der DLL aufgerufen wird (siehe Einsprungpunkte beim Laden oder Entladen einer dynamischen Bibliothek).
Damit ein Aufrufer irgendwelche globalen Namen (wie hier die
Funktionsnamen) ansprechen kann, müssen diese mit __declspec(dllexport)
deklariert werden.
/////////////////////////////////////////////////////////////////////// // // Time-stamp: "(09.05.01 20:00) demodll.cpp [Klaus Wachtler]" // // // Kompilieren mit: // cl -LD -GX demodll.cpp // static int Wert = 0; extern "C" __declspec(dllexport) int summe( int a, int b ) { return a + b; } extern "C" __declspec(dllexport) int immereinsmehr( void ) { if( Wert>6 ) { throw( 125 ); } return Wert++; } // Ab hier kann der ganze Rest entfallen, wenn man ihn nicht braucht: #include <stdio.h> #include <windows.h> #include <winbase.h> // ModulHandle ist das "module handle" resp. "instance handle". BOOL APIENTRY DllMain( HANDLE ModulHandle, DWORD InitOderExit, LPVOID lpReserved ) { switch( InitOderExit ) { case DLL_PROCESS_ATTACH: // Die DLL wird in den Adreßraum eines Prozesses eingeblendet // (z.B. durch ein LoadLibrary() bei explizitem Laden, oder // durch Programmstart bei implizitem Linken über DEF-Dateien). // Entspricht dem Starten eines normalen Programms. // Guter Moment, um globale Variablen zu initialisieren etc. fprintf( stderr, "DllMain: DLL_PROCESS_ATTACH\n" ); break; case DLL_THREAD_ATTACH: // Der zugehörige Prozeß hat einen neuen thread gestartet. // Hier könnte man thrad local storage allokieren (TlsAlloc()) fprintf( stderr, "DllMain: DLL_THREAD_ATTACH\n" ); break; case DLL_THREAD_DETACH: // Der zugehörige Prozeß hat einen thread gestoppt. // Gegenstück zu DLL_THREAD_ATTACH. fprintf( stderr, "DllMain: DLL_THREAD_DETACH\n" ); break; case DLL_PROCESS_DETACH: // Die DLL wird aus dem Prozeßraum eines Prozesses entfernt // (durch Ende des Prozesses oder durch FreeLibrary()). // Gegenstück zu DLL_PROCESS_ATTACH. // Hier kann man globale Objekte wieder aufräumen. fprintf( stderr, "DllMain: DLL_PROCESS_DETACH\n" ); break; default: // sollte eigentlich nie vorkommen! fprintf( stderr, "DllMain: DLL_???\n" ); break; } // Rückgabewert von DllMain() sollte !=(0) sein, wenn alles ok ist. // Die DLL gilt dann als erfolgreich geladen. // Im Fehlerfall sollte DllMain() (0) liefern. // Dann liefert LoadLibrary() dem aufrufenden Prozeß einen Wert // ungleich 0 (also "gescheitert) bei explizitem Linken, bzw. // bei implizitem Linken wird der gerade startende Prozeß // abgeschossen. return TRUE; } // ///////////////////////////////////////////////////////////////////////
Die Beispielbibliothek kann folgendermaßen übersetzt werden:
C:\temp\dynBib\win32>cl -LD -GX demodll.cpp Optimierender Microsoft (R) 32-Bit C/C++-Compiler, Version 12.00.8168, fuer x86 Copyright (C) Microsoft Corp 1984-1998. Alle Rechte vorbehalten. demodll.cpp Microsoft (R) Incremental Linker Version 6.00.8168 Copyright (C) Microsoft Corp 1992-1998. All rights reserved. /out:demodll.dll /dll /implib:demodll.lib demodll.obj Bibliothek demodll.lib und Objekt demodll.exp wird erstelltDie wesentlichen daraus entstehenden Dateien sind demodll.lib und demodll.dll.
Die LIB-Datei wird benötigt, um die Bibliothek fest an ein Programm zu linken.
Die DLL wird sowohl zum festen Linken als auch zum dynamischen Nachladen nach Programmstart benötigt.