Hi, On Saturday 18 April 2009, Bernhard Schiffner wrote: > innerhalb eines "großen" Programms möchte ich zu Laufzeit nur einen > kleinen Bestandteil ändern.
> Ich will nun nicht das ganze Ding neu kompilieren und starten müssen
> (Maschinensteuerung!), sondern nur zu einem geeigneten Augenblick diese
> Änderung einbringen können.
Sind die Änderungen wirklich so begrenzt? Sprich: kannst Du es als Plugin
bezeichnen?
> Hat da irgendwer Erfahrung?
> Was entspricht bei Debian libdl.so? (Irgendwie in libc enthalten?)
Es gibt libdl.so in /lib (Paket: libc6) und in /usr/lib (Paket: libc6-dev).
(Debian Lenny)
Benutzt Du ANSI C oder C++? Bei ersterem musst Du sehr vorsichtig vorgehen,
bei letzterem kann man das C++-Typsystem ausnutzen, um es sicher zu
gestalten.
C++: Du brauchst ein Interface, z.B.:
extern "C" {
MyPluginClass* initPlugin();
bool canUnloadPlugin();
}
Der eigentliche Plugin-Code ist dann in einer von MyPluginClass abgeleiteten
Klasse, deren Instanz von initPlugin zurückgeliefert wird. Ausserdem sollte
diese Klasse einen Instanzen-Counter implementieren, so dass
canUnloadPlugin dir sagen kann ob Du das Plugin entladen darfst.
Laden musst Du natürlich mit RTLD_LOCAL - es sei denn Deine
Interface-Funktionen enthalten einen eindeutigen Teil (Tcl hängt z.B. immer
den Bibliotheksnamen dran - ein "require Tk" lädt libtk.so und
initialisiert mit TkInit()). Die Funktionspointer bekommst Du via dlsym -
daher auch extern "C", sonst musst Du das Name-Mangling vom C++-Compiler
kennen.
Falls Du Qt verwendest schau Dir stattdessen mal QPluginLoader genauer an.
ANSI-C: das Interface wird entsprechend größer und Du musst Dir Gedanken
machen, wie Du absicherst dass es keine Abhängigkeiten gibt während Du
entlädst (dlclose).
Ein paar Tips zum Thema Plugin mit ANSI-C:
Handles als void* herumreichen - das Handle darf damit beliebig komplex
werden, das Plugin weiß worum es geht (cast auf interne Struktur), für die
benutzenden Funktionen ist das Handle nur als Identifikator interessant
(entsprechende Funktionen: newMyHandle, freeMyHandle, doSomethingMyHandle).
Komplexere Objekte, die bei jedem Plugin gleich strukturiert sind bekommen
pseudo-Objektorientierte Strukturen
Nicht jede Funktion einzeln auflösen, sondern von der Interface Funktion
eine Struktur mit Funktionspointern geben lassen:
-- globale plugin.h --
typedef void* MyHandle;
typedef int bool;
struct MyStreamStruct {
int (*read)(MyStreamStruct*self,int length,void*buffer);
int (*write)(MyStreamStruct*self,int length,void*buffer);
void (*closeAndFree)(MyStreamStruct*self);
//internal:
MyHandle _internalhandle;
};
struct MyPluginStruct {
//Plugin-Maintenance:
void (*initPlugin)();
bool canUnload();
//Handle-orientiertes Interface:
MyHandle (*newHandle)();
void (*freeHandle)(MyHandle);
void (*dosomethingHandle)(MyHandle);
//Objektorientiertes Interface:
struct MyStreamStruct* (*newStream)(const char*filename);
};
-- Plugin-locale interface.h --
#include "global/plugin.h"
#ifdef __cplusplus
extern "C"
#endif
MyPluginStruct* initPluginMyExtensionX();
-- Plugin-lokale interface.c --
#include "interface.h"
static void myInitFunction(){ /* ... */ }
/* ... viel Code ...*/
static struct MyPluginStruct myiface = {
myInitFunction,
myCanUnloadFunction,
myNewHandle,
myFreeHandle,
myDoSomething,
NULL /*z.B. wenn das Plugin keine Streams implementiert*/
};
MyPluginStruct* initPluginMyExtensionX(){return &myiface;}
----
Konrad
--
Note: I'm changing my PGP/GPG key soon! New KeyID: 723A6200
Fingerprint: B37C FA75 8C4C 6537 7954 CBC0 CB15 C991 723A 6200
Keyserver: wwwkeys.eu.pgp.net
pgpE5kVElnFEt.pgp
Description: PGP signature
_______________________________________________ Lug-dd maillist - [email protected] https://ssl.schlittermann.de/mailman/listinfo/lug-dd
