Come creare una classe da dll (costruttore in dll)? (С ++) o come caricare dinamicamente la classe da dll?Come creare una classe da dll (costruttore in dll)? (С ++)
risposta
rispondere alla tua domanda rigorosamente, è necessario aggiungere una funzione extern "C" che restituisce il risultato del costruttore:
extern "C" foo* __declspec(dllexport) new_foo(int x) {
return new foo(x);
}
Poi, nel tuo sorgente è possibile utilizzare GetProcAddr su "new_foo" per richiamare la funzione .
Sarà necessario esportare una funzione dalla DLL che chiama il costruttore e restituisce il nuovo oggetto.
Cercare di evitare l'uso di tipi concreti di C++ come parametri di funzione; l'idea delle DLL è che è possibile aggiornarle in modo indipendente, ma un compilatore aggiornato potrebbe disporre std :: string in modo diverso, causando incompatibilità in fase di esecuzione.
Questo è ciò che è alla radice di COM, ad esempio, un sistema di tipo limitato e una funzione standard esportata per ottenere istanze di oggetti.
Suona come se la fonte della DLL non fosse sotto il suo controllo. –
La sorgente DLL è sotto il mio controllo – SomeUser
Se la classe è destinata a essere utilizzata, probabilmente dovrebbe già essere compilata con __declspec (dllexport), quindi è solo questione di convincere il file di intestazione a mettere __declspec (dllimport) nel definizione della classe. In caso contrario, è sempre possibile modificare il file di intestazione. – JesperE
È necessario dichiarare la classe utilizzando la parola chiave __declspec(dllexport)
durante la creazione della DLL. Quando si utilizza la DLL, la classe deve essere dichiarato con __declspec(dllimport)
:
#ifdef COMPILING_DLL
#define DECLSPEC_CLASS __declspec(dllexport)
#else
#define DECLSPEC_CLASS __declspec(dllimport)
#endif
class DECLSPEC_CLASS MyClass
{
...
}
Quando la DLL viene compilata, si dovrebbe aggiungere -DCOMPILING_DLL all'elenco dei definisce.
Quando si utilizza la classe, è necessario collegare staticamente alla DLL, ad esempio passare la libreria di importazione mydll.lib al programma principale.
Se si desidera caricare la DLL in fase di esecuzione, è necessario disporre di una funzione C nella DLL che crea un oggetto e lo restituisce per l'utente. Non c'è modo di cercare dinamicamente un costruttore in una DLL (usando GetProcAddress()).
Invece di esportare ogni metodo della classe utilizzando __declspec, si può anche fare affidamento sul fatto che il compilatore può invocare funzioni virtuali tramite il vtable, così per esempio:
//note: no __declspec
class IPublicInterface
{
virtual ~IPublicInterface() = 0;
virtual void SomeMethod() = 0;
};
//note: no __declspec
class SomeClass : IPublicInterface
{
virtual ~SomeClass() { ... }
virtual void SomeMethod() { ... }
};
//note: this is the only method which needs to be exported from the DLL
IPublicInterface* createSomeClass()
{
return new SomeClass();
}
interfaccia/modello di fabbrica è bello, specialmente se si utilizzerà 'GetProcAddress' e la tabella delle esportazioni .def gestita manualmente –
Poiché la memoria è allocata nella DLL, potrebbe anche esserci un' freeSomClass (IPublicInterface *) 'solo per assicurati che la memoria sia stata liberata correttamente? – Robert
Penso che questa risposta sia sbagliata e dovrebbe essere cancellata. Non è possibile passare un oggetto polimorfico attraverso un limite di plugin, tranne quando lo stesso identico compilatore viene utilizzato sia nel plugin che nell'applicazione. –
Hai un file di intestazione corrispondente e/o file di libreria per accedere alla dll? –
sì, ho la mia intestazione e fonti – SomeUser