近日,在Standard Dll导出静态变量,又出现了一些疑惑,不过还是解决了。
显然不用AFX_EXT_CLASS了。根据本博客上篇文章《类静态成员变量的导出问题》的解决办法,均使用__declspec(dllexport)导出,然后在使用的地方导入。但是还是发现有些繁琐的细节需要注意。
举例来说。A类中含有静态成员变量,在ADll中也是导出的。在BDll中的B类cpp中需要使用A类对象,显然在cpp中直接包含了A的头文件。B类自身也是需要导出的。
由于BDll的所有类都是要导出的,所以为了方便,直接在整个环境(一般在Setting里面)的预编译标志里面加入了导出标志。这样一来,错误就发生了。只要包含了A的头文件就会报链接错误,说找不到那个静态成员变量。实际上,只需要在包含A的头文件之前,再次定义(#define)一个导入标志即可。这里不要使用#undef,因为#undef是会取消宏定义。而再次重新定义,即使用#define,其作用域是从定义的起始地方直到程序末尾(或者#undef取消),如果碰到下一个#define会直接覆盖。虽然我们在这个B的cpp里面,临时定义了一下导入标志,但是在到了一个新的编译单元的时候,因为有全局环境的宏定义,这样问题就解决了。
另外推荐阅读一篇文章,作者写的不错:
===============================================================
=========
在DLL编写时,使用__declspec(dllexport)的作用,它就是为了省掉在DEF文件中手工定义导出哪些函数的一个方法。当然,如果你的DLL里全是C++的类的话,你无法在DEF里指定导出的函数,只能用__declspec(dllexport)导出类。但是,MSDN文档里面,对于__declspec(dllimport)的说明让人感觉有点奇怪,先来看看MSDN里面是怎么说的:
SimpleDLLClass.h
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT
#endif
{
public:
SimpleDLLClass();
virtual ~SimpleDLLClass();
private:
int m_nValue;
};
SimpleDLLClass.cpp
m_nValue=0;
}
}
然后你再使用这个DLL类,在你的APP中include SimpleDLLClass.h时,你的APP的项目不用定义 SIMPLEDLL_EXPORT 所以,DLL_EXPORT 就不会存在了,这个时候,你在APP中,不会遇到问题。这正好对应MSDN上说的__declspec(dllimport)定义与否都可以正常使用。但我们也没有遇到变量不能正常使用呀。 那好,我们改一下SimpleDLLClass,把它的m_nValue改成static,然后在cpp文件中加一行
如果你不知道为什么要加这一行,那就回去看看C++的基础。 改完之后,再去LINK一下,你的APP,看结果如何, 结果是LINK告诉你找不到这个m_nValue。明明已经定义了,为什么又没有了?? 肯定是因为我把m_nValue定义为static的原因。但如果我一定要使用Singleton的Design Pattern的话,那这个类肯定是要有一个静态成员,每次LINK都没有,那不是完了? 如果你有Platform SDK,用里面的Depend程序看一下,DLL中又的确是有这个m_nValue导出的呀。
再回去看看我引用MSDN的那段话的最后一句。 那我们再改一下SimpleDLLClass.h,把那段改成下面的样子:
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT __declspec(dllimport)
#endif
再LINK,一切正常。原来dllimport是为了更好的处理类中的静态成员变量的,如果没有静态成员变量,那么这个__declspec(dllimport)无所谓。
评论