visual studio microsoft files create crear c++ windows dll

c++ - studio - microsoft dll



Exportación de una clase C++ desde una DLL (6)

La mayor parte de mi desarrollo en C / C ++ involucra archivos de módulos monolíticos y absolutamente ninguna clase, así que generalmente cuando necesito crear una DLL con funciones accesibles solo las exporto usando la __declspec(dllexport) estándar __declspec(dllexport) . A continuación, acceda a ellos dinámicamente mediante LoadLibrary() o en tiempo de compilación con un encabezado y un archivo lib.

¿Cómo se hace esto cuando se quiere exportar una clase completa (y todos sus métodos y propiedades públicas)?

¿Es posible cargar dinámicamente esa clase en tiempo de ejecución y, de ser así, cómo?

¿Cómo lo haría con un encabezado y lib para vincular el tiempo de compilación?


¿Qué pasa con el enlace tardío? Como en cargarlo con LoadLibrary () y GetProcAddress ()? Estoy acostumbrado a cargar la biblioteca en tiempo de ejecución y sería genial si pudieras hacer eso aquí.

Entonces hay dos formas de cargar la DLL. El primero es hacer referencia a uno o más símbolos de la DLL (su nombre de clase, por ejemplo), proporcionar un .LIB de importación apropiado y dejar que el enlazador resuelva todo.

El segundo es cargar explícitamente el archivo DLL a través de LoadLibrary.

Cualquiera de los enfoques funciona bien para las exportaciones de funciones de nivel C. Puede dejar que el enlazador lo maneje o llamar a GetProcAddress como anotó.

Pero cuando se trata de clases exportadas, normalmente solo se usa el primer enfoque, es decir, se vincula implícitamente al DLL. En este caso, la DLL se carga al inicio de la aplicación y la aplicación no se carga si no se puede encontrar la DLL.

Si desea establecer un enlace a una clase definida en un archivo DLL, y desea que esa DLL se cargue dinámicamente, en algún momento después del inicio del programa, tiene dos opciones:

  1. Cree objetos de la clase utilizando una función especial de fábrica, que internamente tendrá que usar (un poquito de) ensamblador para "enganchar" los objetos recién creados a sus desplazamientos apropiados. Esto tiene que hacerse en tiempo de ejecución DESPUÉS de que la DLL se haya cargado, obviamente. Una buena explicación de este enfoque se puede encontrar here .

  2. Use una DLL de carga de retraso .

Teniendo en cuenta todo ... probablemente sea mejor ir con enlaces implícitos, en cuyo caso definitivamente quiere utilizar la técnica de preprocesador que se muestra arriba. De hecho, si crea una nueva DLL en Visual Studio y elige la opción "exportar símbolos", estas macros se crearán para usted.

Buena suerte...


Agregar un ejemplo de trabajo simple para exportar una clase C ++ desde un archivo DLL:

El ejemplo que se proporciona a continuación le brinda solo una breve descripción de cómo dll y exe pueden interactuar entre sí (se explica por sí mismo) pero necesita más elementos para agregar para cambiar a un código de producción.

El ejemplo de muestra completo se divide en dos partes

A. Crear una biblioteca .dll (MyDLL.dll)

B. Creando una Aplicación que usa la biblioteca .dll (Aplicación).

Archivo de proyecto A.dll (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 vincula el archivo .dll ya creado:

#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; }


Cuando construya el archivo DLL y el módulo que usará el archivo DLL, tenga algún tipo de definición que pueda usar para distinguir entre uno y otro, entonces puede hacer algo como esto en el archivo de encabezado de su clase:

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

Editar: ¡crashmstr me ganó!


Recientemente me hice exactamente la misma pregunta y resumí mis hallazgos en una publicación de blog . Lo podrías encontrar útil.

Cubre la exportación de clases de C ++ desde un archivo DLL, además de cargarlas dinámicamente con LoadLibrary , y analiza algunos de los problemas que LoadLibrary , como la administración de memoria, la modificación de nombres y las convenciones de llamadas.


Si está dispuesto a poner un vtable en la clase que está exportando, puede exportar una función que devuelve una interfaz e implementar la clase en el archivo .dll, y luego ponerlo en el archivo .def. Puede que tengas que hacer algunos trucos de declaración, pero no debería ser demasiado difícil.

Al igual que COM. :)


Uso algunas macros para marcar el código para importar o exportar

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

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

class DLL MyClassToExport { ... }

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

No sé si podría necesitar hacer algo diferente para trabajar con LoadLibrary