La mayor parte de mi desarrollo C/C++ implica monolítico los archivos del módulo de y absolutamente ninguna de las clases de ningún tipo, por lo general, cuando tengo que hacer un DLL con acceso a las funciones acabo de exportación ellos usando el estándar de __declspec(dllexport) directiva. Luego de acceder a ellos, ya sea de forma dinámica a través de LoadLibrary() o en tiempo de compilación con un encabezado y un archivo lib.

¿Cómo hacer esto cuando se desea exportar toda una clase (y todos sus métodos y propiedades)?

Es posible la carga dinámica de la clase en tiempo de ejecución y si es así, ¿cómo?

Cómo lo harías con un encabezado y lib para el momento de la compilación de vinculación?

InformationsquelleAutor Adam Haile | 2008-08-26

6 Comentarios

  1. 17

    Lo que sobre finales de unión? Como en la carga de
    con LoadLibrary() y
    GetProcAddress() ? Estoy acostumbrado a ser capaz de
    para cargar la biblioteca en tiempo de ejecución y
    sería genial si pudieras hacer eso
    aquí.

    Así que hay dos maneras de cargar la DLL. La primera es hacer referencia a uno o más de los símbolos de la DLL (su nombre de la clase, por ejemplo), el suministro adecuado de importación .LIB y dejar que el enlazador figura todo lo que fuera.

    El segundo es para cargar la DLL explícitamente a través de LoadLibrary.

    Cualquier enfoque funciona bien para el nivel C de la función de exportaciones. Puede dejar que el enlazador de manejar o llamar a GetProcAddress como usted señaló.

    Pero cuando se trata de exportar clases, normalmente sólo el primer método utilizado, es decir, implícitamente enlace a la DLL. En este caso, el archivo DLL se carga en el inicio de la aplicación el tiempo, y la aplicación no se carga si el archivo DLL no se encuentra.

    Si quieres enlazar a una clase definida en un archivo DLL, y desea que el archivo DLL se carga dinámicamente, en algún momento después de la iniciación del programa, usted tiene dos opciones:

    1. Crear objetos de la clase utilizando una fábrica especial de la función, que internamente se han de utilizar (un poco de) ensamblador para «engancharse» en los objetos creados para sus desplazamientos correspondientes. Esto tiene que ser hecho en tiempo de ejecución DESPUÉS de que el archivo DLL se ha cargado, obviamente. Una buena explicación de este enfoque se puede encontrar aquí.

    2. Utilizar un retraso-cargar la DLL.

    Considerando todas las cosas… probablemente es mejor ir con vinculación implícita, en cuyo caso usted definitivamente quiere usar el preprocesador técnica se muestra arriba. De hecho, si se crea un nuevo archivo DLL en Visual Studio y seleccione «exportar símbolos» opción de estas macros se creará para usted.

    Buena suerte…

    • No creo que usted puede utilizar delayload con la importación de clases si las clases tienen funciones virtuales, debido a que las vtables de las clases será importado como símbolos de datos. Importación de datos de símbolos preculdes utilizando delayload.
  2. 17

    Al generar la DLL y el módulo que va a utilizar la DLL, tienen algún tipo de #define que se puede utilizar para distinguir entre uno y otro, entonces usted puede hacer algo como esto en su archivo de encabezado de clase:

    #if defined( BUILD_DLL )
        #define IMPORT_EXPORT __declspec(dllexport)
    #else
        #define IMPORT_EXPORT __declspec(dllimport)
    #endif
    class IMPORT_EXPORT MyClass {
        ...
    };

    Edición: crashmstr me pegaba a él!

    • cómo lidiar con destrozado de clase y constructores (etc.) los nombres de sir.?
    • Esa es la cosa, no hay necesidad de lidiar con los nombres alterados. El __declspec(dllimport) le dice al compilador / enlazador que va a importar es y que hace lo correcto.
    • Ni este ni crashmstr la respuesta tiene nada que ver con la pregunta original. También nula la pregunta no ha sido abordado de manera adecuada.
    • ¿De qué estás hablando? Si usted incluir el archivo de encabezado que define la clase con __declspec(dllimport), y, a continuación, vincular el exe con la biblioteca de importación (resultantes de la construcción de la DLL), el archivo ejecutable resultante con carga automáticamente el archivo DLL en tiempo de ejecución y de importación de la clase, incluyendo todos los métodos de la misma. Los nombres alterados y constructores sobrecargados no son un problema porque todos son manejados por el enlazador y el cargador. No puede ser como completa una respuesta como James Devlin, pero no hay nada de malo con ella, y no la dirección de la pregunta original.
    • De hecho, si usted lee el Señor Devlin la respuesta, dice: «probablemente es mejor ir con vinculación implícita, en cuyo caso usted definitivamente quiere usar el preprocesador técnica se muestra arriba» (el énfasis es mío).
    • Lo siento – me había presumido de que Adán podría haber estado tratando con el compilador de problemas de incompatibilidad. Usted no puede utilizar esta técnica si se intenta exportar clases entre MSVC y MinGW, por ejemplo, debido a discrepancias en el nombre de planchado de esquemas.

  3. 12

    Yo uso algunas macros para marcar el código para la importación o exportación de

    #ifdef ISDLL 
    #define DLL __declspec(dllexport) 
    #endif 
    
    #ifdef USEDLL 
    #define DLL __declspec(dllimport) 
    #endif 
    

    A continuación, declarar la clase en un archivo de encabezado:

    clase DLL MyClassToExport { ... } 
    

    Luego #define ISDLL en la biblioteca, y USEDLL antes de incluir el archivo de encabezado en el lugar que usted desea utilizar la clase.

    No sé si usted puede ser que necesite para hacer algo diferente para trabajar con LoadLibrary

  4. 12

    Agregar un simple ejemplo de trabajo para la exportación de una clase de C++ desde un archivo DLL :

    Dado el ejemplo de abajo le da sólo un breve resumen de cómo dll y exe pueden interactuar entre sí (autoexplicativo ), pero se necesita más cosas para agregar para cambiar un código de producción.

    Total de la muestra ejemplo está dividido en dos parte

    A. Creación de un .dll (biblioteca de MyDLL.dll)

    B. Creación de una Aplicación que utiliza .dll (biblioteca de la Aplicación).

    A. .dll fichero de proyecto (MyDLL.dll):

    1. dllHeader.h

    #ifdef  MYDLL_EXPORTS 
    #define DLLCALL __declspec(dllexport)   /* Should be enabled before compiling 
                                               .dll project for creating .dll*/
    #else
    #define DLLCALL __declspec(dllimport)  /* Should be enabled in Application side
                                              for using already created .dll*/
    #endif
    
    //Interface Class
    class ImyMath {
    public:
        virtual ~ImyMath() {;}
        virtual int Add(int a, int b) = 0;
        virtual int Subtract(int a, int b) = 0;
    };
    
    //Concrete Class
    class MyMath: public ImyMath {
    public:
        MyMath() {}
        int Add(int a, int b);
        int Subtract(int a, int b);
        int a,b;
    };
    
    // Factory function that will return the new object instance. (Only function
    // should be declared with DLLCALL)
    extern "C" /*Important for avoiding Name decoration*/
    {
        DLLCALL ImyMath* _cdecl CreateMathObject();
    };
    
    //Function Pointer Declaration of CreateMathObject() [Entry Point Function]
    typedef ImyMath* (*CREATE_MATH) ();

    2. dllSrc.cpp

    #include "dllHeader.h"
    
    //Create Object
    DLLCALL ImyMath* _cdecl CreateMathObject() {
        return new MyMath();
    }
    
    int MyMath::Add(int a, int b) {
        return a+b;
    }
    
    int MyMath::Subtract(int a, int b) {
        return a-b;
    }

    B. Proyecto de Aplicación que carga y enlace a los ya creados .archivo dll:

     #include <iostream>
    #include <windows.h>
    #include "dllHeader.h"
    
    int main()
    {
        HINSTANCE hDLL = LoadLibrary(L"MyDLL.dll"); //L".\Debug\MyDLL.dll"
    
        if (hDLL == NULL) {
            std::cout << "Failed to load library.\n";
        }
        else {
            CREATE_MATH pEntryFunction = (CREATE_MATH)GetProcAddress(hDLL,"CreateMathObject");
            ImyMath* pMath = pEntryFunction();
            if (pMath) {
                std::cout << "10+10=" << pMath->Add(10, 10) << std::endl;
                std::cout << "50-10=" << pMath->Subtract(50, 10) << std::endl;
            }
            FreeLibrary(hDLL);
        }
        std::cin.get();
        return 0;
    }
    • Gracias. Sin la Clase de Interfaz de enfoque en esta respuesta, me fue tener que poner todo en la .h archivo para evitar errores del vinculador.
    • ¿por qué necesita una fábrica de función? Si sin de fábrica de la función, ¿cómo debo hacer?
  5. 7

    Recientemente me hice exactamente la misma pregunta, y resumir mis conclusiones en un post en el blog. Usted puede encontrar que es útil.

    Cubre la exportación de clases de C++ desde un archivo DLL, así como la carga de forma dinámica y con LoadLibrary, y analiza algunas de las cuestiones en torno a que, como la administración de memoria, el nombre de destrozarlo y convenciones de llamada.

  6. 0

    Si usted está dispuesto a poner una vtable en la clase que usted va a exportar, puede exportar una función que devuelve un interfaz e implementar la clase en el .dll, luego ponerlo en el .archivo def. Usted podría tener que hacer alguna declaración engaño, pero no debería ser demasiado difícil.

    Como COM. 🙂

Dejar respuesta

Please enter your comment!
Please enter your name here