我一直搞不明白__declspec(dllimport)的作用在哪里。比如现在我新建一个使用共享MFC DLL的规则DLL工程:DllDlg。然后我新建两个文件:DllApi.h和DllApi.cpp。DllApi.h作为接口文件,DllApi.cpp作为实现文件。
接着在DllApi.h声明一个函数:
__declspec(dllexport) void HelloWorld();
在DllApi.cpp写这个函数的实现:
void HelloWorld()
{
AfxMessageBox(_T("HelloWorld"));
}
这样外部的应用程序或dll就能调用HelloWorld函数。但是我见到更多似乎是脱裤子放屁式的做法,首先自定义导出宏,然后在添加预处理器。以上例为例:
首先是在DllApi.h声明:
#ifdef _EXPORTING
#define API_DECLSPEC __declspec(dllexport)
#else
#define API_DECLSPEC __declspec(dllimport)
#endif
API_DECLSPEC void HelloWorld();
在DllApi.cpp写这个函数的实现:
void HelloWorld()
{
AfxMessageBox(_T("HelloWorld"));
}
最后在DllDlg工程里添加预处理器:_EXPORTING。这等于告诉大家:定义了这个预处理器的就是把函数导出,不定义这个预处理器的就是把函数导入。
但是比较这两种做法,效果有区别吗?说实话我看不出有任何区别。那为什么我们还是热衷于定义一个导出宏,然后添加预处理器的做法吗?__declspec(dllimport)的作用到底在哪里?
附msdn 2005对__declspec(dllimport)的解释:
如果一个程序使用 DLL 定义的公共符号,就说该程序是在导入公共符号。为使用 DLL 生成的应用程序创建头文件时,在公共符号的声明上使用 __declspec(dllimport)。不论是用 .def 文件导出还是用 __declspec(dllexport) 关键字导出,__declspec(dllimport) 关键字均有效。
若要提高代码的可读性,请为 __declspec(dllimport) 定义一个宏,然后使用此宏声明每个导入的符号:
复制代码
#define DllImport __declspec( dllimport )
DllImport int j;
DllImport void func();
在函数声明上使用 __declspec(dllimport) 是可选操作,但如果使用此关键字,编译器将生成更有效的代码。但是,为使导入的可执行文件能够访问 DLL 的公共数据符号和对象,必须使用 __declspec(dllimport)。请注意,DLL 的用户仍然需要与导入库链接。
对 DLL 和客户端应用程序可以使用相同的头文件。为此,请使用特殊的预处理器符号来指示是生成 DLL 还是生成客户端应用程序。例如:
复制代码
#ifdef _EXPORTING
#define CLASS_DECLSPEC __declspec(dllexport)
#else
#define CLASS_DECLSPEC __declspec(dllimport)
#endif
class CLASS_DECLSPEC CExampleA : public CObject
{ ... class definition ... };