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

Attachment: pgpE5kVElnFEt.pgp
Description: PGP signature

_______________________________________________
Lug-dd maillist  -  [email protected]
https://ssl.schlittermann.de/mailman/listinfo/lug-dd

Antwort per Email an