Cosa è sicuro per un sistema plug-in C ++?

I sistemi plug-in in C ++ sono difficili perché l’ABI non è definito correttamente e ogni compilatore (o versione di esso) segue le sue regole. Tuttavia, COM su Windows mostra che è ansible creare un sistema plug-in minimale che consente ai programmatori con diversi compilatori di creare plug-in per un’applicazione host utilizzando una semplice interfaccia.

Siamo pratici, e lasciamo lo standard C ++, che non è molto utile a questo riguardo, a parte un minuto. Se voglio scrivere un’app per Windows e Mac (e opzionalmente Linux) che supporta i plug-in C ++ e se voglio dare agli autori di plug-in una scelta abbastanza ampia di compilatori (diciamo versioni meno di 2 anni di Visual C ++ , GCC o compilatore C ++ di Intel), su quali funzionalità del C ++ potrei contare?

Naturalmente, presumo che i plug-in vengano scritti per una piattaforma specifica.

In cima alla mia testa, ecco alcune funzionalità del C ++ a cui riesco a pensare, con quello che penso sia la risposta:

  • layout vtable, usare gli oggetti attraverso classi astratte? (sì)
  • tipi built-in, puntatori? (sì)
  • structs, unions? (sì)
  • eccezioni? (no)
  • Funzioni “C” esterne? (sì)
  • stdcall non-extern “C” funziona con i tipi di parametri incorporati? (sì)
  • non “stdcall” non “extern” C “funziona con i tipi di parametri definiti dall’utente? (no)

Gradirei qualsiasi esperienza tu abbia in quell’area che potresti condividere. Se sei a conoscenza di qualsiasi app di successo con un sistema plug-in C ++, va bene.

Carl

Il Dobb’s Journal ha un articolo: Building Your Own Plugin Framework: Parte 1 che è una buona lettura sull’argomento. È l’inizio di una serie di articoli che copre l’architettura, lo sviluppo e l’implementazione di un framework di plugin multipiattaforma C / C ++.

Si potrebbe anche voler prendere in considerazione la possibilità di sostituire l’interfaccia del plugin convenzionale con un’interfaccia di scripting. Ci sono alcuni ottimi legami per diversi linguaggi di scripting in C / C ++ che hanno già risolto il tuo problema. Potrebbe non essere una ctriggers idea costruirci sopra. Ad esempio, dai un’occhiata a Boost.Python .

Qt ha un ottimo sistema per i plugin che ho usato in passato. Usa il sistema meta-object di Qt per superare molti dei problemi tipicamente riscontrati quando si cerca di sviluppare plugin C ++.

Un esempio è come funziona Q_DECLARE_INTERFACE , per impedire l’utilizzo di un plug-in incompatibile. Un altro è la chiave di build , per essere sicuri di caricare il plugin corretto per la tua architettura, sistema operativo, compilatore. Se non usi il sistema di plugin di Qt, queste sono cose di cui dovrai preoccuparti e inventare le soluzioni da solo. Non è necessariamente scienza missilistica, e non sto dicendo che non ci riuscirai, ma i ragazzi di Trolltech sono piuttosto intelligenti e ci hanno messo un po ‘a pensarci, e preferirei usare quello che hanno creato piuttosto che reinventare la ruota da solo .

Un altro esempio è che RTTI in genere non funziona attraverso i confini della DLL, ma quando si utilizza Qt, cose come qobject_cast che si basano sul sistema meta-object funzionano attraverso i confini della DLL.

Penso che tu sia sicuro creando un sistema di plugin basato su:

  • Confezionamento delle funzionalità dei plugin nella libreria (.dll, .so, ecc.)
  • Richiede che il plugin esponga le esportazioni chiave in lingua C.
  • Richiede che il plugin attui (e restituisca un puntatore / riferimento a) un’interfaccia C ++ astratta.

Probabilmente il sistema di plugin C ++ di maggior successo: il buon vecchio Adobe Photoshop . E se no, uno dei formati di synth virtuali come VSTi, ecc.

Il libro Imperfect C ++ di Matthew Wilson ha una bella informazione su questo.

Il consiglio sembra essere: se usi lo stesso compilatore (o un compilatore), puoi usare C ++, altrimenti è meglio usare C come interfaccia sopra al tuo codice C ++.

ACE ha un’architettura plug-in multipiattaforma.

Check-out:

  1. DLL ACE
  2. ACE DLL Manager

Suggerirei di controllare il libro
La guida del programmatore ACE

Firefox gira su XPCOM ( http://www.mozilla.org/projects/xpcom/ ). È ispirato a Microsoft COM ma è multipiattaforma.

Ho il mio motore di gioco che ha un sistema plug-in C ++.

Ho un po ‘di codice nei file header in modo che venga inserito nell’unità di compilazione del plugin.

Le funzioni più grandi che vivono nel motore principale sono chiamate tramite una funzione C esportata (il plugin chiama MyObject_somefunction (MyObject * obj) che nel motore chiama solo obj-> somefunction ()). Se chiamare una funzione C è brutto per i tuoi gusti, quindi con alcuni trucchi per le intestazioni, quando l’intestazione è inclusa nel plugin, avere la funzione membro # definita per chiamare la funzione C:

 #if defined(IN_THE_PLUGIN) void MyObject::somefunction() { MyObject_somefunction(this); } #endif 

Le funzioni virtuali devono essere pure o il codice risiede nel file di intestazione. Se non sto ereditando da una class e sto semplicemente istanzandone una, il codice di funzione virtuale può vivere nel motore, ma la class deve esportare alcune funzioni C per creare e distruggere l’object chiamato dal plugin.

Fondamentalmente, i trucchi che ho usato, con l’objective di mantenere l’indipendenza totale della piattaforma, sono solo delle esportazioni di C e trucchi dei file di intestazione.