我不明白使用DLL的.def文件的意义.
它似乎取代了在您的DLL代码中使用显式导出的需要(即显式__declspec(dllexport))但是我不能在不使用这些时生成lib文件,然后在使用DLL时创建链接器问题.
那么在与客户端应用程序链接时如何使用.def,它们是否取代了使用头文件或.lib文件的需要?
我发现同时使用__declspec(dllexport)和.def文件在创建可移植DLL时很有用,即可以从使用不同编译器编译的代码或使用不同编译器设置调用的DLL.
只需将__declspec(dllexport)放在函数声明上就会导致这些函数被DLL"导出"(至少在Windows上),以便可以从DLL外部调用它们.
但是,在构建中添加一个列出所有导出函数的.def文件,可以阻止Microsoft编译器(例如)将前导下划线和尾随参数宽度信息添加到导出的函数名中(至少与__stdcall结合使用时)指令,对于可移植性也很有用).例如函数声明
void foo(int i);
如果你不小心调用约定和.def文件使用,最终可能导出为"_foo @ 4".
将GetProcAddress()调用作为加载和在运行时显式挂钩到DLL的一部分时,保持符号表中没有这种名称修饰的导出函数名称非常方便.即在运行时获取指向上述函数foo()的指针(假设它完全被导出),理想情况下你只想调用:
HANDLE dllHandle = LoadLibrary("mydll.dll"); void* fooFcnPtr = GetProcAddress(dllHandle, "foo");
当然有一些适当的错误案例检查!
在构建DLL时,在函数声明中使用.def文件加__stdcall,__ declspec(dllexport)和extern"C"将确保上述客户端代码适用于各种编译器和编译器设置.
我的理解是.def文件提供了__declspec(dllexport)语法的替代方法,还具有能够显式指定导出函数的序数的额外好处.如果仅通过序数导出某些函数,这可能很有用,它不会显示有关函数本身的大量信息(例如:许多OS内部DLL的导出函数仅按顺序).
请参阅参考页面.
请注意,.def文件中的名称必须与二进制文件中的名称匹配.因此,如果您使用带有'extern"C"{...}'的C或C++,名称将不会被破坏; 否则,您必须为用于生成DLL的特定编译器版本使用正确的受损名称.__declspec()函数自动完成所有操作.
对于那些感兴趣的人......为了能够链接到dll和def文件,你还需要一个lib文件.在Windows中,这可以使用'LIB'工具从def进行.请参阅下面的命令行方式示例.
lib /machine:i386 /def:sqlite3.def
希望这有助于其他人.