导出DLL中的静态数据

Gay*_*yan 31 c++ windows linker-errors dllexport

我有一个DLL,其中包含一个静态成员的类.我用__declspec(dllexport)它来使用这个类的方法.但是当我将它链接到另一个项目并尝试编译它时,我得到静态数据的"未解析的外部符号"错误.

例如,在DLL中,Test.h

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

在DLL中,Test.cpp

#include "Test.h"

int Test::d;
Run Code Online (Sandbox Code Playgroud)

在使用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)
Run Code Online (Sandbox Code Playgroud)

但是.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
Run Code Online (Sandbox Code Playgroud)

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

PS该代码最初是为Linux开发的,而.so /二进制组合的工作没有问题

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

And*_*bel 17

在cprogramming.com的这个主题中,建议静态变量是dll的本地变量而不是导出的.

以下讨论摘要

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

  • 尝试将使用静态成员的所有方法体移动到.cpp文件中,这些文件被编译到dll中,并且不能在应用程序中内联,这可能会成为它. (2认同)

Ghi*_*rny 11

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

#ifdef EXPORTING
#define DECLSPEC __declspec(dllexport)
#else
#define DECLSPEC __declspec(dllimport)
#endif
Run Code Online (Sandbox Code Playgroud)

然后在类声明中使用它:

class DECLSPEC Test{
protected:
    static int d;
public:
    static void m(){}
}
Run Code Online (Sandbox Code Playgroud)

因此,在Test.cpp中(或者在DLL项目中有意义的地方),您可以指定要导出以便使用dllexport导出它:

#define EXPORTING
#include "Test.h"

int Test::d;
Run Code Online (Sandbox Code Playgroud)

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

是否有意义?

  • 是的,我还读到dllimport是可选的.我的理解是你可以省略它,但是dllexport不应该用于导入dll的应用程序:否则编译器认为它是由应用程序导出的,查找不存在的相应定义,这会产生错误消息. (3认同)

Ram*_* B. 5

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

以下是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
Run Code Online (Sandbox Code Playgroud)