2009-04-02 14 views
28

Quali sono i suggerimenti per l'implementazione di un sistema di stile plugin?Implementazione di un sistema di plugin in C o C++

+0

Correlati - se non duplicati - http://stackoverflow.com/questions/384121/creating-a-module-system-dynamic-loading-in-c – ChrisF

+0

Dai un'occhiata a [questo tutorial] (http: // sourcey.com/building-a-simple-cpp-cross-platform-plugin-system/). Hanno pubblicato questo tutorial come un progetto multipiattaforma funzionante chiamato [Pluga] (http://sourcey.com/pluga/) che utilizza una libreria denominata [LibSourcey] (https://github.com/sourcey/libsourcey). – aggregate1166877

risposta

29

In C (e penso anche C++ anche se non l'ho fatto da solo), questo è in genere eseguito utilizzando moduli caricati in modo dinamico. Le API: s per tali sono dipendenti dalla piattaforma.

Su POSIX (Linux), si utilizza la famiglia di funzioni dlopen(). Fondamentalmente si costruisce il plug-in separatamente, quindi lo si carica in fase di esecuzione, si cercano i suoi simboli per nome e possono quindi chiamarli.

Per Win32, c'è LoadLibrary() che fa qualcosa di molto simile, si crea il codice in una DLL.

Per un pratico wrapper che rende tutto questo facile e trasparente, controlla l'API di GLib GModule.

+0

Per Win32, raccomanderei LoadLibraryEx con il flag LOAD_WITH_ALTERED_SEARCH_PATH impostato. – dalle

+0

è così che lo faccio. C++ non ha un ABI definito quindi non è possibile utilizzarlo in modo affidabile per caricare le classi C++ in modo dinamico. mentre c fa. Se hai bisogno del caricamento C++, devi esporre tutti i tuoi moduli con un'interfaccia c (es. COM fa esponendo 4 funzioni) – gbjbaanb

+0

+1 solo per il collegamento a GModule – drahnr

0

Ho avuto un certo successo con un sistema abbastanza ingenuo:

  • Creare API Specification per i plug-in
  • Utilizzare un Singleton Plug-in Manager
  • Usa LoadLibrary/GetProcAddress fase di esecuzione basato collegamento dinamico
  • Implementate Inversione di evento in base controllo movimentazione per notificare i plug-in
9

Nel '9 2/'93 time frame Ho lavorato su un'architettura plugin per Aldus PageMaker, che è stato codificato in C++. PageMaker è stato realizzato su un framework OOP C++ chiamato VAMP, che ha assistito la sua portabilità tra Mac OS e Windows.

Quindi abbiamo provato a utilizzare le funzionalità di C++ per creare un'architettura di plugin. Ciò si è rivelato molto problematico per le classi C++ a causa del cosiddetto problema della classe base fragile. Ho continuato a scrivere un articolo che è stato pubblicato su riviste e che ho presentato a OOPSLA '93 in un seminario di riflessione. Ho anche preso contatto con Bjarne Stroustrup in una conferenza di Usenix a Portland e ho continuato a dialogare con lui per diversi mesi, dove ha sostenuto la questione di trattare il fragile problema di classe base per mio conto. (Ahimè, altri problemi erano considerati più importanti in quel momento.)

Microsoft ha introdotto il sistema COM/DCOM e per quella piattaforma che è stata vista come una soluzione praticabile al problema. C++ potrebbe essere utilizzato come linguaggio di implementazione per COM tramite classi astratte utilizzate per definire le interfacce COM.

Tuttavia, in questi giorni gli sviluppatori si allontanano dalla COM/DCOM.

Al contrario, NeXT ha escogitato un'architettura plug-in utilizzando l'Objective C nei primi anni '90 nel framework NeXT Step. Oggi vive vivacemente su Mac OS X su computer Apple e piattaforme importanti come l'iPhone.

Invio l'Objective C abilitato risolvendo il problema del plugin in modo superiore.

Personalmente ritengo che il fragile problema di classe base del C++ sia il difetto più fatale.

Se sono stati la costruzione di un'architettura a plugin con la famiglia C-based delle lingue, sarebbe farlo utilizzando Objective C.

+0

Hai un link alla tua carta? O un riferimento da qualche parte? – coryan

+0

l'idea è che se si modifica la classe base, si può rompere tutte le classi derivate - tuttavia, penso che questo si applica a tutti i plugin oo. Vale certamente per jscript.net: http: //blogs.msdn.com/ericlippert/archive/2004/01/07/virtual-methods-and-brittle-base-classes.aspx – gbjbaanb

+1

Qui una citazione di uno dei miei articoli: http://citeseerx.ist.psu.edu/viewdoc /summary?doi=10.1.1.51.418 in fondo alla pagina c'è una vista o download link per ottenere il .pdf: http://citeseerx.ist.psu.edu/viewdoc/download;jsessionid=1B865C7B3133C75949ECE12B20D3D140 ? doi = 10.1.1.51.418 & rep = rep1 & type = pdf – RogerV

3

E 'meglio utilizzare un framework come ACE (http://www.cs.wustl.edu/~schmidt/ACE.html) che protegge (il migliore possibile) dalla codifica specifica della piattaforma.

ACE contiene un framework di plugin basato su librerie condivise che è possibile utilizzare per creare applicazioni assemblate dinamicamente.

Per un'astrazione di livello superiore controllare CIAO (http://www.cs.wustl.edu/~schmidt/CIAO.html) l'implementazione C++ Open Source del modello di componente CORBA.

5

Questo potrebbe non essere quello che stai cercando, ma potresti incorporare un linguaggio di scripting nella tua applicazione, come Lua. Lua è stato progettato per essere incorporato in altri programmi e utilizzato come linguaggio di scripting per scrivere plugin. Credo che sia abbastanza facile aggiungere l'interprete Lua al tuo programma, anche se non conosco Lua, quindi non posso garantire l'efficacia di una soluzione. Altri con più esperienza con Lua, si prega di aggiungere commenti sulla propria esperienza con l'incorporamento di Lua in un'altra applicazione.

Questo ovviamente significherebbe che i plug-in devono essere scritti in Lua. Se non ti piace Lua, allora gli de-facto standard Perl, gli interpreti Python e Ruby sono tutti scritti in C e possono essere incorporati in un programma C. Conosco un certo numero di programmi che usano queste lingue come estensioni del linguaggio di scripting.

Tuttavia, non so cosa stai cercando, poiché la tua domanda è un po 'vaga. Forse maggiori informazioni su ciò che volete che le persone siano in grado di fare con detti plug-in sarebbero appropriate. Per alcune attività, un linguaggio di scripting in piena regola può essere un po 'eccessivo.

0

Ho scritto una libreria plugin Pugg che carica classi C++ da file dll e qui è la logica che ho usato: esporta

utente una funzione C da dll che ha un nome univoco. Questo nome deve essere abbastanza unico in quanto le funzioni non possono essere distinte usando i loro argomenti durante il caricamento da DLL.

La funzione C registra una o più classi di fabbrica denominate "Driver". Ogni classe Driver è associata a una stringa. Quando l'applicazione principale vuole creare una classe, raccoglie la classe factory relativa utilizzando la stringa associata. Ho anche implementato un sistema di controllo della versione per non caricare vecchi plugin.

Il caricamento di Dll viene eseguito utilizzando le funzioni LoadLibraryA e GetProcAddress (attualmente Pugg funziona su Windows).

Una cosa degna di nota è che l'applicazione principale e le DLL devono essere compilate utilizzando lo stesso compilatore e utilizzando le stesse opzioni di compilazione (modalità di rilascio/debug, impostazioni di ottimizzazione, versioni di stl ecc ...). Altrimenti potrebbero esserci problemi con la mappatura delle classi.

10

la migliore piattaforma e la consulenza indipendente dalla lingua che posso dare è questo:

Progetta la tua intera applicazione in tutto lo SDK plugin.

IMO, un plug-in SDK non dovrebbe essere un ripensamento. Se si progetta l'applicazione per essere sostanzialmente un guscio vuoto che carica plugin, quindi le caratteristiche principali sono implementate nel proprio SDK, si ottengono i seguenti vantaggi:

  • alta modularità dei componenti e netta separazione di scopo (it tipo di forze vostra architettura di essere buono)
  • Si costringe lo SDK per essere veramente buono
  • permette altri sviluppatori di terze parti per rendere estremamente potente, core-livello dispone così
  • nuovi sviluppatori/assunzioni possono facilmente iniziare lavora su una nuova importante funzionalità senza dover toccare l'app principale - possono fare tutto il loro lavoro in un plug-in (quale pre Bocchette li avvitare qualsiasi altra cosa)

In C/C++, probabilmente si utilizza librerie a collegamento dinamico e sia puntatori a funzione (C) o interfacce (classi costituiti unicamente da metodi virtuali puri, per C++). Tuttavia, anche se usi Javascript, ti consiglio comunque l'architettura di cui sopra.

2

Ho scritto un articolo su come implementare un sistema di plugin utilizzando le librerie di collegamento dinamico. L'articolo è scritto dal punto di vista di un programmatore di Windows, ma la tecnica può essere applicata ad un ambiente di tipo Linux/Unix.

L'articolo può essere trovato qui: http://3dgep.com/?p=1759

Il punto principale è, è necessario creare una DLL "comune" che è implicitamente legata sia l'applicazione principale (l'applicazione core) e dalle implementazioni di plugin. I plugin possono quindi essere esplicitamente collegati e caricati dinamicamente in fase di esecuzione dall'applicazione principale.

L'articolo mostra anche come è possibile condividere in modo sicuro l'istanza statica (singleton) di una classe su più DLL utilizzando la DLL "comune".

L'articolo mostra anche come esportare una funzione "C" o variabili da una DLL e utilizzare le funzioni esportate nell'applicazione in fase di esecuzione.