====== Initialisierung und Deinitialisierung von dynamischen Libraries ======
Beim Laden/Entladen einer dynamischen Library besteht häufig Notwendigkeit, einige Funktionen automatisiert auszuführen. Beim Laden z.B. müssen globale Variablen initialisiert werden (davon abgesehen, dass globale Variablen in einer Library möglichst zu vermeiden sind). Beim Entladen z.B. müssen irgendwelche Aufräumarbeiten durchgeführt werden (z.B. Schließen von Logfiles).
:!: Diese Notwendigkein besteht insbesondere dann, wenn die dynamischen Library nicht zur Laufzeit des Programms geladen werden (**dlopen()** unter Linux bzw. **LoadLibrary()** unter Windows), sondern wenn sie gleich beim Starten des Programms durch den Betriebssystem-Loader gelinkt werden. In diesem Fall sind die Libraries bereits geladen, bevor die main()-Funktion die Kontrolle übernimmt. Die Initialisierungs-Funktion wird in diesem Fall ebenfalls **vor** und die Deinitialisierungs-Funktion **nach** der main()-Funktion aufgerufen (wenn die main() durch return() oder exit() bereits die Kontrolle abgegeben hat).
Es gibt verschiedene Mechanismen, dies zu realisieren.
===== Unix- / GCC-Variante =====
Man exportiert mittels **%%__attribute__(())%%** Funktionen zum Initialisieren und Finalisieren der Library:
void __attribute__ ((constructor)) lib_initialize(void);
void __attribute__ ((destructor)) lib_finalize(void);
// Called when the library is loaded and before dlopen() returns.
void lib_initialize(void)
{
// Lib-initialization code here.
}
// Called when the library is unloaded and before dlclose() returns.
void lib_finalize(void)
{
// Clean-up code here.
}
In der veralteten Variante lauten diese Symbole **_init()** bzw. **_fini()** - die sind //deprecated// und sollen daher nicht mehr benutzt werden.
:!: Shared Libraries sollen nicht mit dem GCC Schalter **-nostartfiles** oder **-nostdlib** kompiliert/gelinkt werden! Durch diese Parameter werden die Constructor/Destructor-Routinen unterdrückt!
Links:
* Linux Programmer's Manual: [[http://man7.org/linux/man-pages/man3/dlopen.3.html]] (unter //"Initialization and finalization functions"//)
* The Linux Dokumentation Project: [[http://tldp.org/HOWTO/Program-Library-HOWTO/miscellaneous.html]] (unter //"Library constructor and destructor functions"//)
* Implementing DllMain in a linux shared library: [[http://tdistler.com/2007/10/05/implementing-dllmain-in-a-linux-shared-library]]
* Automatically executed functions when loading shared libraries: [[http://stackoverflow.com/questions/9759880/automatically-executed-functions-when-loading-shared-libraries]]
Solaris Compiler nutzen **%%#pragma init%%** and **%%#pragma fini%%** für diesen Zweck:
#pragma init(lib_initialize)
#pragma fini(lib_finalize)
void lib_initialize(void)
{
// ...
}
void lib_finalize(void)
{
// ...
}
===== Windows =====
// Return TRUE on success and FALSE if an error occurs. Returning FALSE will cause the library to be unloaded.
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
// Lib-initialization code here.
break;
case DLL_PROCESS_DETACH:
// Clean-up code here.
break;
}
return(TRUE);
}
Links:
* DllMain entry point: [[https://msdn.microsoft.com/en-us/library/ms682583.aspx]]
----
Stand: 11.04.2016
EOF