2012-02-15 21 views
5

He leído algunos documentos que le da ejemplos sencillos sobre las funciones compatibles con C.¿Cómo puedo importar DLL de una clase C++ dentro de un espacio de nombres

__declspec(dllexport) MyFunction(); 

estoy okey con eso. Escribo una pequeña aplicación que usa las funciones de este dll. Utilicé vinculación explícita con

LoadLibrary() 

función. Las funciones de estilo C funcionan sin problemas. Pero cuando escribo mi clase como

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

} 
#endif 

compila bien y se crea Dll. Mientras trabajaba con las funciones de estilo C, simplemente estaba tomando un puntero de función de las funciones LoadLibrary() y GetProcAddress (...).

Mi uso previo es

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 

Pero ahora no tengo ni idea de cómo puedo crear una instancia de mi clase? ¿Cómo puedo usar un enlace explícito o un enlace implícito?

Cualquier ayuda con una muestra de código sería apreciada.

Respuesta

6

Si intenta crear una instancia de una clase, necesita conocer su estructura en tiempo de compilación. Puede lograrlo creando una clase abstracta que defina los métodos de instancia que la clase importada deberá redefinir. Por ejemplo:

//interface.h 

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

A continuación, en su archivo DLL, puede incluir la interfaz.h, heredan TestInterface y redefinir los métodos de pura virtual:

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

A continuación, puede definir una función en la DLL que asigna un objeto de prueba:

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

Y, por último, al importar el archivo DLL, busque el símbolo "allocate_test" y úselo:

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

Dos puntos: primero, 'TestInterface' no necesita (ni debería tener) el miembro de datos privados, y segundo, si va a pasar el nombre de la función a' GetProcAddress', la función es mejor 'extern "C" '(de lo contrario, tiene que pasar el nombre destrozado). Y por supuesto, en 'allocate_test', quisiste hacer' return new Test; ', not' return new TestInterface(); '(que no compilará). –

+0

Tienes razón, lo hice a toda prisa y me perdí algunas cosas. – mfontanini

2

En primer lugar, tenga en cuenta que esta es una particularidad de Microsoft. Las diferentes reglas se mantendrán para otros sistemas.

Escribir cosas como lo hizo no funciona, o al menos, es doloroso. Usted necesita usar __declspec(dllexport) en la DLL que define las funciones , pero __declspec(dllimport) al compilar el código que invoca las funciones de otra DLL. La forma habitual de manejar esto es para uso algún nombre de macro específica especificando el archivo DLL, y hacer algo como:

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

Pon esto en un encabezado que se incluye en todas las cabeceras en su DLL, y definir MYMODULE_DLL en la línea de comandos del proyecto.

Además, es posible exportar una clase entera:

class MYMODULE_EXPORT DllTest 
{ 
    // ... 
}; 

Esto tiene el efecto de exportación o importación de todas las funciones y miembros estáticos de la clase.

+0

Tengo esta pieza en mi código, mientras pongo aquí rasgué esa parte. Todavía no ayuda con la creación y el uso de instancias de mi clase, durante la importación. – accfews

+1

OK. Me di cuenta de que estás usando 'GetProcAddress'. Lo que significa que las funciones no pueden ser funciones miembro, solo 'extern" C "' (de lo contrario, no puede nombrarlas). Tendrá que definir una interfaz abstracta y una función 'extern 'C" 'que devuelve una instancia. –

Cuestiones relacionadas