2011-01-26 8 views
5

Estoy buscando implementar una arquitectura de complemento en nuestra aplicación actual (Unix, C++) y he estado revisando las opciones (pendiente de aprobación) dentro de las bibliotecas de Boost.Opción Boost Plugin

Editar: Estoy buscando agregar dinámicamente clases en tiempo de ejecución.

Boost.Plugin

Boost.Reflection

Boost.Extension

Me preguntaba qué gustos de la experiencia/opinión está en estas y otras implementaciones.

+1

Ha publicado las soluciones propuestas para un problema que no indicó. ¿Cuáles son sus requisitos? –

Respuesta

4

Eh. Sólo se utiliza dlopen y dlsym junto con un par de extern "C" static funciones que debe definirse en el archivo DLL

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

un vistazo plugin-gestor de archivos ".so" ".dll" o y cargarlos en un
map<string, pair< plugin*(*)(arg_pack*), errno_t(*)(plugin*)> >

a continuación, puede operaciones de búsqueda un plugin basado en un nombre (por encima de la cuerda) y conseguir que la 'constructor' o 'destructor'

ver también: gmodule

+0

¿Comprobación de compatibilidad ABI/API? –

+0

@Vlad ABI -> 'extern" C "' garantiza la modificación del estilo c. API -> 'dlsym' para cargar todas las funciones relevantes de la biblioteca. Si falta alguno, entonces no es un complemento y debe descartar los punteros de funciones y 'dlclose' la biblioteca. – KitsuneYMG

+1

extern "C" garantiza el cambio, pero imagine que la firma ha cambiado, o la interfaz que proporciona el host ha cambiado, y el complemento espera algo diferente, la mejor apuesta sería colgarse, pero las consecuencias podrían ser muy drásticas (es decir, los malos precios provienen de la negociación) sistema, que hace que una empresa quiebre en un par de segundos). Debe haber un conjunto de controles decentes que aseguren que se cumpla con el contrato que se espera. Básicamente, este debería ser un objetivo principal de los marcos de plugins, no solo envolviendo dlopen ... –

1

No puede cargar clases en tiempo de ejecución ya que C++ es un lenguaje compilado y las clases no existen en tiempo de ejecución. Los objetos (instancias de clases) lo hacen.

Lo que puede hacer es cargar bibliotecas compartidas en tiempo de ejecución y hacer que creen objetos de una determinada interfaz.

La implementación mínima del complemento definiría la interfaz de su complemento y la interfaz de la función de fábrica que va a crear objetos con esa interfaz. Va a cargar la biblioteca compartida en tiempo de ejecución, buscar la función de fábrica con un cierto nombre y llamar a la función de fábrica para crear un objeto. Luego utiliza ese objeto a través de la interfaz:

// 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

Ahora, esto no funcionará en plataformas que no sean POSIX, podría haber problemas de montón cuando el objeto se asigna en el montón del complemento y se elimina en las aplicaciones principales. Sin mencionar compatibilidad API/ABI ... –

+0

@Vlad: estamos hablando de Unix aquí. –

+0

@Maxim: Aún así, debe asegurarse de que el complemento y el host sean compatibles con ABI (es decir, compilador igual o compatible, etc.), además de compatibles con API. Es por eso que necesitas algunas cosas de nivel superior como Boost, y usar cowboy dlopen es ... ya sabes. –

Cuestiones relacionadas