2012-02-15 15 views
5

ho letto alcuni documenti che dà semplici esempi di funzioni compatibili con C.Come posso importare dll di una classe C++ all'interno di uno spazio dei nomi

__declspec(dllexport) MyFunction(); 

Sono okey con quello. Scrivo una piccola applicazione utilizza le funzioni di questa DLL. Ho usato il collegamento esplicito con

LoadLibrary() 

funzione. Le funzioni in stile C funzionano senza problemi. Ma quando scrivo la mia lezione come

namespace DllTest 
{ 
class Test 
{ 
public: 
    __declspec(dllexport) Test(); 
    __declspec(dllexport) void Function(int); 
    __declspec(dllexport) int getBar(void); 
private: 
    int bar; 
}; 

} 
#endif 

compila bene e Dll viene creato. Mentre lavoravo con le funzioni in stile C stavo semplicemente prendendo un puntatore a funzione dalle funzioni LoadLibrary() e GetProcAddress (...).

mio utilizzo precedente è

typedef void (*Function)(int); 

int main() 
{ 
    Function _Function; 
    HINSTANCE hInstLibrary = LoadLibrary(TEXT("test.dll")); 

    if (hInstLibrary) 
    { 
     _Function = (Function)GetProcAddress(hInstLibrary,"Function"); 
    if (_Function) 
    { 
     // use the function 

Ma ora non ho idea di come posso istanziare la mia classe? Come posso utilizzare il collegamento esplicito o il collegamento implicito?

Qualsiasi aiuto con un esempio di codice sarebbe apprezzato.

risposta

6

Se si sta tentando di creare un'istanza di una classe, è necessario conoscerne la struttura in fase di compilazione. È possibile ottenere ciò creando una classe astratta che definisca i metodi di istanza che la classe importata dovrà ridefinire. Ad esempio:

//interface.h 

class TestInterface 
{ 
public: 
    virtual void Function(int) = 0; 
    virtual int getBar(void) = 0; 
}; 

Successivamente, nella DLL è possibile includere l'interfaccia.h, ereditare TestInterface e ridefinire i metodi pura virtuale:

//test.h 
namespace DllTest { 
    class Test : public TestInterface 
    { 
    public: 
     Test(); 
     void Function(int); 
     int getBar(void); 
    private: 
     int bar; 
    }; 
}; 

È quindi possibile definire una funzione nella DLL che alloca un oggetto di prova:

extern "C" __declspec(dllexport) TestInterface *allocate_test() { 
    return new DllTest::Test(); 
} 

E infine, quando si importa la DLL, cerca il simbolo "allocate_test" e usalo:

TestInterface *(*test_fun)() = (TestInterface *(*test_fun)())GetProcAddress(hInstLibrary,"allocate_test"); 
TestInterface *test_ptr = test_fun(); 
test_ptr->Function(12); //use you object 
+2

Due punti: in primo luogo, 'TestInterface' non ha bisogno (né dovrebbe avere) del membro dati privato, e in secondo luogo, se sta per passare il nome della funzione a' GetProcAddress', la funzione dovrebbe essere meglio 'extern "C" '(altrimenti, deve passare il nome maciullato). E, naturalmente, in 'allocate_test', intendevi fare' return new Test; ', non' return new TestInterface(); '(che non verrà compilato). –

+0

Hai ragione, l'ho fatto di fretta e ho perso alcune cose. – mfontanini

2

Innanzitutto, si noti che questa è una particolarità Microsoft. Diverse regole verranno mantenute per altri sistemi.

Scrivere le cose come hai fatto non funziona, o almeno è doloroso. È 012 necessario utilizzare __declspec(dllexport) nella DLL che definisce le funzioni , ma __declspec(dllimport) durante la compilazione del codice che richiama le funzioni da un'altra DLL. Il solito modo di gestire questo obiettivo è quello uso alcune specifiche macro nome specificando la DLL, e fare qualcosa di simile:

#ifdef __WIN32 
#ifdef MYMODULE_DLL 
#define MYMODULE_EXPORT __declspec(dllexport) 
#else 
#define MYMODULE_EXPORT __declspec(dllimport) 
#endif 
#else 
#define MYMODULE_EXPORT 
#endif 

Mettere questo in un colpo di testa che è incluso in tutte le intestazioni nel vostro DLL, e definire MYMODULE_DLL sulla riga di comando del progetto.

Inoltre, è possibile esportare un'intera classe:

class MYMODULE_EXPORT DllTest 
{ 
    // ... 
}; 

Questo ha l'effetto di esportare o importare tutte le funzioni e le membri statici della classe.

+0

Ho questo pezzo nel mio codice, mentre inserisco qui ho strappato quella parte. Ancora non aiuta a creare e ad usare istanze della mia classe, durante l'importazione. – accfews

+1

OK. Ho appena notato che stai usando 'GetProcAddress'. Ciò significa che le funzioni non possono essere funzioni membro, solo "extern" C "' (altrimenti, non puoi nominarle). Dovrai definire un'interfaccia astratta e una funzione "extern" C "' che restituisca un'istanza. –

Problemi correlati