2009-10-04 3 views

risposta

3

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 .

3

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.

+0

Suona come se la fonte della DLL non fosse sotto il suo controllo. –

+0

La sorgente DLL è sotto il mio controllo – SomeUser

+0

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

10

È 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()).

+1

Puoi citare una fonte per l'ultima affermazione? AFAIK a ctor ha un nome storpiato e puoi chiamare GetProcAddress usando quel nome. Cosa ti fermerebbe? – MSalters

+0

Sì, tecnicamente hai ragione. – JesperE

3

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(); 
} 
+0

interfaccia/modello di fabbrica è bello, specialmente se si utilizzerà 'GetProcAddress' e la tabella delle esportazioni .def gestita manualmente –

+0

Poiché la memoria è allocata nella DLL, potrebbe anche esserci un' freeSomClass (IPublicInterface *) 'solo per assicurati che la memoria sia stata liberata correttamente? – Robert

+0

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. –