c++ c dll

Archivos.def C/C++ DLL



(6)

No entiendo el sentido de usar archivos .def con DLL.

Parece que reemplaza la necesidad de usar exportaciones explícitas dentro de su código DLL (es decir, explicita __declspec (dllexport)), sin embargo, no puedo generar un archivo lib cuando no los uso, lo que luego crea problemas de enlazador al usar el DLL.

Entonces, ¿cómo se usa .defs cuando se vincula con la aplicación cliente, ¿reemplazan la necesidad de usar un encabezado o un archivo .lib?


Los archivos .DEF eran más comunes en las ventanas de 16 bits donde generalmente eran la única forma de especificar qué símbolos se deberían exportar.

Además, proporcionaron un medio para especificar exportaciones por valor ordinal (@ 1, @ 2 etc.) en lugar de por nombre. Este método de búsqueda de símbolos se utilizó cuando el rendimiento era realmente importante, como en los controladores de video.


No he trabajado mucho con DLL, pero entiendo que para las funciones exportadas de C ++, debe usar "__declspec (dllexport)", y para las funciones exportadas de C, debe escribir el archivo .def. Eso es probablemente porque las funciones C ++ soportan la sobrecarga, pero las funciones C no.


Tengo entendido que los archivos .def no especifican qué API se debe exportar. Solo contiene las apis exportadas y sus números ordinales. Si desea exportar una API en particular, debe especificar __declspec (dllexport) en la definición de api y __declspec (dllimport) en la declaración.

La ventaja del archivo def es que le ayuda a mantener la compatibilidad de la palabra clave con los dlls ya realzados. es decir, mantiene los números ordinales para apis. Supongamos que agrega una nueva API en el dll, luego el enlazador mira su archivo .def generando el número ordinal para el ne wapi de forma que los números ordinales para las antiguas apis estén intactos.

Por lo tanto, si el código de cliente usa la última DLL, no rompe las API existentes.


Tengo entendido que los archivos .def proporcionan una alternativa a la sintaxis __declspec (dllexport), con el beneficio adicional de poder especificar explícitamente los ordinales de las funciones exportadas. Esto puede ser útil si exporta algunas funciones solo por ordinal, que no revela tanta información sobre la función en sí (p. Ej., Muchas de las funciones de exportación del DLL interno del SO solo por ordinal).

Ver la página de referencia .

Tenga en cuenta que los nombres en el archivo .def deben coincidir con los nombres en el binario. Entonces, si usas C o C ++ con ''extern'' C "{...} '', los nombres no se destrozarán; de lo contrario, debe utilizar los nombres correctos destrozados para la versión específica del compilador utilizado para generar el archivo DLL. La función __declspec () hace esto todo automáticamente.


Para aquellos interesados ​​aún ... para poder vincular al archivo dll y def, también necesita un archivo lib. En Windows esto se puede hacer desde la definición utilizando la herramienta ''LIB''. Vea a continuación un ejemplo de la forma de línea de comandos para hacer esto.

lib /machine:i386 /def:sqlite3.def

Espero que esto ayude a otros.


Encuentro el uso de ambos __declspec (dllexport) y el archivo .def juntos para ser útil en la creación de DLL portátiles, es decir, DLL que se pueden llamar desde código compilado con un compilador diferente o con configuraciones de compilador diferentes.

El simple hecho de poner __declspec (dllexport) en las declaraciones de su función hará que esas funciones sean "exportadas" por su DLL (al menos en Windows) para que puedan ser llamadas desde fuera de la DLL.

Sin embargo, al agregar un archivo .def que enumera todas las funciones exportadas, puede evitar que los compiladores de Microsoft (por ejemplo) agreguen un subrayado inicial y una información de ancho de parámetro posterior al nombre de la función exportada (al menos cuando se combina con el __stdcall directiva, también útil para la portabilidad). Por ejemplo, la declaración de la función

void foo(int i);

podría terminar exportándose como "_foo @ 4" si no tiene cuidado con la invocación de convenciones y el uso de archivos .def.

Mantener los nombres de las funciones exportadas en la tabla de símbolos sin este tipo de decoración resulta muy útil cuando se hacen llamadas a GetProcAddress () como parte de la carga y el enlace explícito de una DLL en el tiempo de ejecución. es decir, para obtener un puntero a la función anterior foo () (suponiendo que se haya exportado) en tiempo de ejecución, lo ideal es que solo desee llamar:

HANDLE dllHandle = LoadLibrary("mydll.dll"); void* fooFcnPtr = GetProcAddress(dllHandle, "foo");

¡Con alguna verificación de caso de error apropiada, por supuesto!

El uso de un archivo .def más __stdcall, __declspec (dllexport) y extern "C" en las declaraciones de su función al construir su DLL garantizará que el código anterior del lado del cliente funcione para una amplia gama de compiladores y configuraciones del compilador.