内容选择VC2008 的 MSDN文档,摘录在此。
1. 可以使用两种方法将公共符号导入到应用程序中或从 DLL 导出函数:
-
生成 DLL 时使用模块定义 (.def) 文件
-
在主应用程序的函数定义中使用关键字 __declspec(dllimport) 或 __declspec(dllexport)
(1)使用 .def 文件
模块定义 (.def) 文件是包含一个或多个描述 DLL 各种属性的 Module 语句的文本文件。如果不使用 __declspec(dllimport) 或 __declspec(dllexport) 导出 DLL 函数, 则 DLL 需要 .def 文件。
可以使用 .def 文件导入到应用程序中或从 DLL 导出。
(2)使用 __declspec
Visual C++ 用 __declspec(dllimport) 和 __declspec(dllexport) 取代以前在 16 位版的 Visual C++ 中使用的 __export 关键字。
不使用 __declspec(dllimport) 也能正确编译代码,但使用 __declspec(dllimport) 使编译器可以生成更好的代码。编译器之所以能够生成更好的代码,是因为它可以确定函数是否存在于 DLL 中,这使得编译器可以生成跳过间接寻址级别的代码,而这些代码通常会出现在跨 DLL 边界的函数调用中。但是,必须使用 __declspec(dllimport) 才能导入 DLL 中使用的变量。
如果有正确的 .def 文件 EXPORTS 节,则不需要 __declspec(dllexport)。添加 __declspec(dllexport) 是为了提供不使用 .def 文件从 .exe 或 .dll 文件导出函数的简单方法。
Win32 可移植可执行文件格式旨在最小化为修改导入而必须访问的页数。为此,它将所有程序的所有导入地址都放在一个称为“导入地址表”的位置。这使得加载程序在访问这些导入时可以只修改一两页。
1 使用 __declspec(dllexport) 从 DLL 导出
若要导出函数,__declspec(dllexport) 关键字必须出现在调用约定关键字的左边(如果指定了关键字)。例如:
__declspec(dllexport) void __cdecl Function1(void);
若要导出类中的所有公共数据成员和成员函数,关键字必须出现在类名的左边,如下所示:
class __declspec(dllexport) CExampleExport : public CObject { ... class definition ... };
2.使用 __declspec(dllimport) 从 DLL 导入 与1 类似
3 导出 C++ 函数,使得 C 语言可执行文件能够调用
如果在用 C++ 编写的 DLL 中,有希望从 C 语言模块访问的函数,应使用 C 链接而不是 C++ 链接来声明这些函数。
若要指定 C 链接,请为函数声明指定 extern "C"。例如:
extern "C" __declspec( dllexport ) int MyFunc(long parm1);
4 导出 C 函数以用于 C 或 C++ 语言可执行文件
如果在用 C 编写的 DLL 中有希望从 C 语言或 C++ 语言模块访问的函数,则应使用 __cplusplus 预处理器宏确定正在编译的语言,然后,如果是从 C++ 语言模块使用,则用 C 链接声明这些函数。如果使用此技术并为 DLL 提供头文件,则这些函数可以原封不动地由 C 和 C++ 用户使用。以下代码演示可由 C 和 C++ 客户端应用程序使用的头文件:
// MyCFuncs.h #ifdef __cplusplus extern "C" { // only need to export C interface if // used by C++ source code #endif __declspec( dllimport ) void MyCFunc(); __declspec( dllimport ) void AnotherCFunc(); #ifdef __cplusplus } #endif如果需要将 C 函数链接到 C++ 可执行文件,并且函数声明头文件没有使用上面的技术,则在 C++ 源文件中添加下列内容以防止编译器修饰 C 函数名:
extern "C" { #include "MyCHeader.h" }