导出DLL中的静态数据

我有一个包含静态成员的类的DLL。 我使用__declspec(dllexport)来使用这个类的方法 。 但是当我链接到另一个项目,并尝试编译它时,我得到了静态数据的“无法parsing的外部符号”错误。

例如在DLL,Test.h中

 class __declspec(dllexport) Test{ protected: static int d; public: static void m(){int x = a;} } 

在DLL中,Test.cpp

 #include "Test.h" int Test::d; 

在使用Test的应用程序中,我称之为m()。

我也尝试使用__declspec(dllexport)分别为每个方法,但我仍然得到静态成员相同的链接错误。

如果我使用dumpbin检查DLL(.lib),我可以看到符号已经被导出。

例如,该应用程序在链接时提供以下错误:

 1>Main.obj : error LNK2001: unresolved external symbol "protected: static int CalcEngine::i_MatrixRow" (?i_MatrixRow@CalcEngine@@1HA) 

但.lib的dumpbin包含:

 Version : 0 Machine : 14C (x86) TimeDateStamp: 4BA3611A Fri Mar 19 17:03:46 2010 SizeOfData : 0000002C DLL name : CalcEngine.dll Symbol name : ?i_MatrixRow@CalcEngine@@1HA (protected: static int CalcEngine::i_MatrixRow) Type : data Name type : name Hint : 31 Name : ?i_MatrixRow@CalcEngine@@1HA 

我无法弄清楚如何解决这个问题。 我究竟做错了什么? 我怎样才能克服这些错误?

PS该代码最初是为Linux开发的,.so / binary组合可以毫无问题地工作

编辑:在给定的情况下,静态variables不是由应用程序直接引用,但方法是内联,因为它在标题。 我能够通过将方法移动到.cpp文件来解决链接错误。

在cprogramming.com的这个线程中,建议静态变量是dll本地的,不能导出。

下面的讨论总结

静态成员不是通过调用应用程序中的代码直接访问,只能通过dll中类的成员函数来访问。 但是有几个内联函数访问静态成员。 这些函数将内联扩展到调用应用程序代码,使调用应用程序直接访问静态成员。 这将违反上面提到的发现,静态变量是本地的DLL,不能从调用应用程序引用。

我的猜测是,使用该DLL的类应该在头中看到dllimport而不是dllexport 如果我是正确的,通常可以通过定义一个预处理宏来实现,如:

 #ifdef EXPORTING #define DECLSPEC __declspec(dllexport) #else #define DECLSPEC __declspec(dllimport) #endif 

然后在类声明中使用它:

 class DECLSPEC Test{ protected: static int d; public: static void m(){} } 

所以在Test.cpp中(或者在你的DLL项目中有意义的地方),你可以指定你正在导出,所以它将被导出为dllexport

 #define EXPORTING #include "Test.h" int Test::d; 

而另一个没有定义EXPORTING的项目将会看到dllimport

是否有意义?

对于Windows DLL, __declspec(dllexport)__declspec(dllimport)之间有一个特定的区别,编译DLL时应该使用dllexport ,编译连接到这个DLL的程序时应该使用dllimport 定义这个的标准方法是用宏。

以下是visual studio的例子:

 // The following ifdef block is the standard way of creating macros which make exporting // from a DLL simpler. All files within this DLL are compiled with the DLL_EXPORTS // symbol defined on the command line. this symbol should not be defined on any project // that uses this DLL. This way any other project whose source files include this file see // DLL_API functions as being imported from a DLL, whereas this DLL sees symbols // defined with this macro as being exported. #ifdef DLL_EXPORTS #define DLL_API __declspec(dllexport) #else #define DLL_API __declspec(dllimport) #endif