2011-01-26 2 views
5

Je cherche à implémenter une architecture de plugin dans notre application actuelle (Unix, C++) et j'ai passé en revue les options (en attente d'approbation) dans les bibliothèques Boost.Choix du plugin Boost

Editer: Je cherche à ajouter dynamiquement des classes à l'exécution.

Boost.Plugin

Boost.Reflection

Boost.Extension

Je me demandais ce que l'expérience everyones/opinion est sur ces questions et d'autres mises en œuvre.

+1

Vous avez publié vos solutions proposées pour un problème que vous n'avez pas indiqué. Quelles sont vos exigences? –

Répondre

4

Eh. Nous venons tout juste utilisé dlopen et dlsym avec une paire de extern "C" static fonctions qui doivent être définies dans le dll

extern "C" static plugin* create(arg_pack*); 
extern "C" static errno_t destroy(plugin*); 

Jetez un coup d'oeil plugin-gestionnaire pour « .dll » ou « fichiers .so » et les charger dans un
map<string, pair< plugin*(*)(arg_pack*), errno_t(*)(plugin*)> >

Vous pouvez ensuite rechercher un plug-in basé sur un nom (la chaîne ci-dessus) et l'obtenir est « constructeur » ou « destructor »

voir aussi: gmodule

+0

Vérification de compatibilité ABI/API? –

+0

@Vlad ABI -> 'extern" C "' garantit le maniement de style c. API -> 'dlsym' pour charger toutes les fonctions pertinentes de la bibliothèque. S'il en manque, ce n'est pas un plugin et vous devez supprimer les pointeurs de fonctions et 'dlclose' la librairie. – KitsuneYMG

+1

extern "C" garantit le mangling, mais imaginez que la signature a changé, ou que l'interface hôte a changé, et plugin s'attend à autre chose, le meilleur pari serait de planter, mais les conséquences pourraient être très dramatiques système, ce qui rend une entreprise en faillite en quelques secondes). Il devrait y avoir une série de vérifications décentes pour s'assurer que tout contrat prévu est respecté. Cela devrait être un objectif principal des frameworks plugins, et pas seulement dlopen ... –

1

Vous ne pouvez pas charger les classes au moment de l'exécution car C++ est un langage compilé et les classes n'existent pas au moment de l'exécution. Objets (instances de classes) font.

Ce que vous pouvez faire est de charger les bibliothèques partagées au moment de l'exécution et de les faire créer des objets d'une certaine interface.

Une implémentation de plug-in minimale définirait l'interface de votre plug-in et l'interface de la fonction d'usine qui va créer des objets avec cette interface. Vous allez charger la bibliothèque partagée à l'exécution, trouver la fonction d'usine avec un certain nom et appeler la fonction d'usine pour créer un objet. Ensuite, vous utilisez cet objet via l'interface:

// plugin.h start 
#include <memory> 

struct PlugIn // interface 
{ 
    virtual ~PlugIn() = 0; 
    virtual void doSomething() = 0; 
}; 

extern "C" { 

typedef std::auto_ptr<PlugIn> PlugInFactoryFn(); 

// A plugin .so must export this one factory function. 
std::auto_ptr<PlugIn> createPlugIn(); 

} 
// plugin.h end 

// somewhere in you application 
#include "plugin.h" 
#include <assert.h> 
#include <dlfcn.h> 

std::auto_ptr<PlugIn> loadPlugIn(char const* filename) 
{ 
    void* so = dlopen(filename, RTLD_NOW | RTLD_LOCAL); 
    assert(so); 
    void* factory_function = dlsym(so, "createPlugIn"); 
    assert(factory_function); 
    return reinterpret_cast<PlugInFactoryFn*>(factory_function)(); 
} 

int main() 
{ 
    std::auto_ptr<PlugIn> a(loadPlugIn("a.so")); 
    std::auto_ptr<PlugIn> b(loadPlugIn("b.so")); 
    a->doSomething(); 
    b->doSomething(); 
} 
+0

Maintenant, cela ne fonctionnera pas sur les plates-formes non-POSIX, il pourrait y avoir des problèmes de tas lorsque l'objet est alloué sur le tas du plugin et supprimé dans les applications principales. Sans oublier la compatibilité API/ABI ... –

+0

@Vlad: nous parlons ici d'Unix. –

+0

@Maxim: Vous devez néanmoins vous assurer que le plugin et l'hôte sont compatibles avec ABI (c'est-à-dire compilateur compatible ou similaire, etc.), et compatibles API. C'est pourquoi vous avez besoin de quelque chose de plus haut niveau comme Boost, et l'utilisation de cowboy dlopen est ... vous savez. –