.def 文件 C/C++ DLL
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/366228/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
.def files C/C++ DLLs
提问by cweston
I am not understanding the point of using .def files with DLLs.
我不明白将 .def 文件与 DLL 一起使用的意义。
It seems that it replaces the need to use explicit exports within your DLL code (ie. explicit __declspec(dllexport)) however I am unable to generate a lib file when not using these which then creates linker issues later when using the DLL.
似乎它取代了在 DLL 代码中使用显式导出的需要(即显式 __declspec(dllexport)),但是当不使用这些时我无法生成 lib 文件,然后在使用 DLL 时会产生链接器问题。
So how do you use .defs when linking with the client application, do they replace the need to use a header or .lib file?
那么在与客户端应用程序链接时如何使用 .defs,它们是否取代了使用头文件或 .lib 文件的需要?
采纳答案by Nick
My understanding is that .def files provide an alternative to the __declspec(dllexport) syntax, with the additional benefit of being able to explicitly specify the ordinals of the exported functions. This can be useful if you export some functions only by ordinal, which doesn't reveal as much information about the function itself (eg: many of the OS internal DLL's export functions only by ordinal).
我的理解是 .def 文件提供了 __declspec(dllexport) 语法的替代方案,具有能够显式指定导出函数的序数的额外好处。如果您仅按序导出某些函数,这会很有用,这不会显示有关函数本身的太多信息(例如:许多操作系统内部 DLL 的导出函数仅按序导出)。
See the reference page.
请参阅参考页。
Note that the names in the .def file must match the names in the binary. So if you using C or C++ with 'extern "C" { ... }', the names will not be mangled; otherwise you must use the correct mangled names for the specific version of the compiler used to generate the DLL. The __declspec() function does this all automatically.
请注意,.def 文件中的名称必须与二进制文件中的名称匹配。因此,如果您将 C 或 C++ 与 'extern "C" { ... }' 一起使用,名称将不会被破坏;否则,您必须为用于生成 DLL 的编译器的特定版本使用正确的重整名称。__declspec() 函数会自动完成这一切。
回答by
I find the use of both __declspec(dllexport) and the .def file together to be useful in creating portable DLLs, i.e. DLLs that can be called from code compiled with a different compiler or with different compiler settings.
我发现同时使用 __declspec(dllexport) 和 .def 文件对于创建可移植的 DLL 很有用,即可以从使用不同编译器或不同编译器设置编译的代码中调用的 DLL。
Just putting __declspec(dllexport) on your function declarations will cause those functions to be "exported" by your DLL (at least on Windows) so that they can be called from outside the DLL.
只需将 __declspec(dllexport) 放在您的函数声明上就会导致这些函数被您的 DLL(至少在 Windows 上)“导出”,以便可以从 DLL 外部调用它们。
However, adding to the build a .def file that lists all of your exported functions lets you stop Microsoft compilers (for example) from adding a leading underscore and trailing parameter-width information to the exported function name (at least when combined with the __stdcall directive, also useful for portability). E.g. the function declaration
但是,将列出所有导出函数的 .def 文件添加到构建中可以阻止 Microsoft 编译器(例如)向导出的函数名称添加前导下划线和尾随参数宽度信息(至少在与 __stdcall 结合使用时)指令,对于可移植性也很有用)。例如函数声明
void foo(int i);
could end up being exported as "_foo@4" if you aren't careful about calling convention and .def file usage.
如果您不注意调用约定和 .def 文件的使用,最终可能会被导出为“_foo@4”。
Keeping the exported function names in the symbol table free of such name-decoration comes in really handy when making GetProcAddress() calls as part of loading and hooking into a DLL explicitly at runtime. i.e. to get a pointer to the above function foo() (assuming it was exported at all) at runtime, you ideally just want to call:
在运行时将 GetProcAddress() 调用作为加载和挂钩到 DLL 的一部分时,让符号表中的导出函数名称没有这种名称修饰非常方便。即要在运行时获取指向上述函数 foo() 的指针(假设它完全被导出),理想情况下您只想调用:
HANDLE dllHandle = LoadLibrary("mydll.dll");
void* fooFcnPtr = GetProcAddress(dllHandle, "foo");
With some appropriate error case checking of course!
当然还有一些适当的错误案例检查!
Use of a .def file plus __stdcall, __declspec(dllexport) and extern "C" on your function declarations when building your DLL will ensure that the above client-side code will work for a wide range of compilers and compiler settings.
在构建 DLL 时,在函数声明中使用 .def 文件加上 __stdcall、__declspec(dllexport) 和 extern "C" 将确保上述客户端代码适用于各种编译器和编译器设置。
回答by cweston
For those interested still... to be able to link to the dll and def file you also require a lib file. In windows this can be made from the def using the 'LIB' tool. See below for an example of the command line way of doing this.
对于那些仍然感兴趣的人...为了能够链接到 dll 和 def 文件,您还需要一个 lib 文件。在 Windows 中,这可以通过使用“LIB”工具的 def 来实现。有关执行此操作的命令行方式的示例,请参见下文。
lib /machine:i386 /def:sqlite3.def
Hope this helps others.
希望这对其他人有帮助。
回答by Ferruccio
.DEF files were more common in 16-bit windows where they were usually the only way to specify which symbols should be exported.
.DEF 文件在 16 位窗口中更为常见,它们通常是指定应导出哪些符号的唯一方法。
In addition, they provided a means to specify exports by ordinal value (@1, @2 etc.) rather than by name. This method of looking up symbols was used when performance was really important, such as in video drivers.
此外,它们提供了一种按序数值(@1、@2 等)而不是按名称指定导出的方法。这种查找符号的方法在性能非常重要时使用,例如在视频驱动程序中。
回答by chappar
My understanding is that .def files do not actually specifies which all apis need to be exported. It just contains the apis exported and their ordinal numbers. If you want to actually export a particular api, you need to specify __declspec(dllexport) in the definition of the api and __declspec(dllimport) at the declaration.
我的理解是 .def 文件实际上并未指定需要导出哪些所有 api。它只包含导出的 apis 及其序数。如果要实际导出某个特定的api,则需要在api 的定义中指定__declspec(dllexport) 并在声明中指定__declspec(dllimport)。
The advantage of def file is that, it helps you to maintain the backword compatibility with the already realsed dlls. i.e it maintains the ordinal numbers for apis. Suppose you add a new api in the dll, then the linker looks at your .def file genearate the ordinal number for the ne wapi such that the ordinal numbers for the old apis are intact.
def 文件的优点在于,它可以帮助您保持与已经实现的 dll 的后文兼容性。即它维护 apis 的序数。假设您在 dll 中添加了一个新的 api,那么链接器会查看您的 .def 文件,生成新 wapi 的序数,以便旧 api 的序数保持不变。
So, if the client code uses the latest dll, it does not break the existing apis.
因此,如果客户端代码使用最新的 dll,它不会破坏现有的 api。
回答by Hosam Aly
I haven't worked with DLLs much, but my understanding is that for exported C++ functions, you shold use the "__declspec(dllexport)", and for exported C functions you should write the .def file. That's probably because C++ functions support overloading, but C functions do not.
我很少使用 DLL,但我的理解是,对于导出的 C++ 函数,您应该使用“__declspec(dllexport)”,对于导出的 C 函数,您应该编写 .def 文件。这可能是因为 C++ 函数支持重载,而 C 函数不支持。