C++ 导出 DLL 中的静态数据

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2479784/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 23:35:18  来源:igfitidea点击:

Exporting static data in a DLL

c++windowslinker-errorsdllexport

提问by Gayan

I have a DLL which contains a class with static members. I use __declspec(dllexport)in order to make use of this class's methods. But when I link it to another project and try to compile it, I get "unresolved external symbol" errors for the static data.

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

e.g. In DLL, Test.h

例如在 DLL 中,Test.h

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

In DLL, Test.cpp

在 DLL 中,Test.cpp

#include "Test.h"

int Test::d;

In the application which uses Test, I call m().

在使用 Test 的应用程序中,我调用了 m()。

I also tried using __declspec(dllexport) for each method separately but I still get the same link errors for the static members.

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

If I check the DLL (the .lib) using dumpbin, I could see that the symbols have been exported.

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

For instance, the app gives the following error at link time:

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

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

But the dumpbin of the .lib contains:

但是 .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

I can't figure out how to solve this. What am I doing wrong? How can I get over these errors?

我不知道如何解决这个问题。我究竟做错了什么?我怎样才能克服这些错误?

P.S. The code was originally developed for Linux and the .so/binary combination works without a problem

PS 该代码最初是为 Linux 开发的,.so/binary 组合没有问题

EDIT: In the given case, the static variables are not directly referred by the application but the method is inlined since it's in the header. I was able to resolve the link errors by moving the methods to the .cpp file.

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

采纳答案by Anders Abel

In thisthread at cprogramming.com it is suggested that a static variable is local to the dll and not exported.

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

Summary of discussion below

下面的讨论摘要

The static member is not accessed directly by code in the calling application, only through member functions of the class in the dll. However there are several inlinefunctions accessing the static member. Those functions will be inline expanded into the calling applications code makeing the calling application access the static member directly. That will violate the finding referenced above that static variables are local to the dll and cannot be referenced from the calling application.

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

回答by Ghislain Fourny

My guess is that the class which uses the DLL should see dllimportinstead of dllexportin the header. If I am correct, this can typically be achieved by defining a preprocessor macro like:

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

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

and then use it in the class declaration:

然后在类声明中使用它:

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

So that in Test.cpp (or wherever it makes sense in your DLL project) you can specify that you are exporting so that it will be exported with dllexport:

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

#define EXPORTING
#include "Test.h"

int Test::d;

while the other project, which does not define EXPORTING, will see dllimport.

而另一个未定义 EXPORTING 的项目将看到dllimport

Does it make sense?

是否有意义?

回答by Ramon Zarazua B.

With Windows DLLs, there is a specific distinction between __declspec(dllexport)vs __declspec(dllimport), dllexportshould be used when compiling the DLL, dllimportshould be used when compiling programs that link to this DLL. The standard way of defining this would be with a macro.

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

The following is the visual studio example:

以下是 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