DLL中的全局初始化变量



是否可以使用一个DLL模块中的全局变量来初始化其他DLL模块的全局变量?如果是,如何?

我使用的是Microsoft Visual Studio 17.3.6,并使用带有一些C文件的C++/CLI包装类。我在一个更大的项目中,但我已经把一个较小的例子放在一起,展示了这种行为。

我本以为它会这样工作。在一个项目中有四个文件,file1.c文件1.h,在第二个项目中则有file2.cfile2.h。它们被构建到两个dll,file1.dll和file2.dll。第一个项目定义了file1_EXPORTS预处理器符号,第二个项目定义file2_EXPORTS。包括为清楚起见省略的防护装置。

文件1.c

#include <file1.h>
#include <file2.h>
structure1_t struct1 = {
&struct2
};

文件1.h

typedef struct
{
structure2_t* ptr;
} structure1_t;
#ifdef file1_EXPORTS
#define EXPORT_SYMBOL __declspec(dllexport)
#else
#define EXPORT_SYMBOL __declspec(dllimport)
#endif
EXPORT_SYMBOL structure1_t struct1;

文件2.h:

typedef struct
{
int* i;
} structure2_t;
#if defined (file2_EXPORTS)
#define EXPORT_SYMBOL __declspec(dllexport)
#else
#define EXPORT_SYMBOL __declspec(dllimport)
#endif
EXPORT_SYMBOL structure2_t struct2;

文件2.c

#include <file2.h>
#include <file1.h>
int i;
structure2_t struct2 = {
&i
};

但是,它不能像这样编译。出现错误C2099: initializer is not a constant。当我将行(在file2.h中(#define EXPORT_SYMBOL __declspec(dllimport)更改为#define EXPORT_SYMBOL extern时,会出现链接器错误LNK2001: unresolved external symbol struct2LNK1120: 1 unresolved externals。唯一对我有效的组合是将定义留空,例如#define EXPORT_SYMBOL。我必须做的其他更改是将定义保留在file1.h中,否则程序将在下一步失败。

现在,这些都已正确构建,并创建了库file1.dll和file2.dll。假设存在使用DLL的第三个文件file3.cpp

#include <file1.h>
#include <file2.h>
#include <iostream>
int main(void)
{
std::cout << struct1.ptr << std::endl;
std::cout << struct2.i << std::endl;
return 0;
}

它打印:

0000000000000000
0000000000000000

所以,我的问题是,有没有什么方法可以在没有NULL指针的情况下工作(例如,struct1有指向struct2的指针,struct2有指向整数的指针(?为什么程序会这样做,是因为file3.cpp只看到标头中的声明,而变量从未正确初始化吗?其他变体和解决方案可能是具有一个初始化函数,将所需的值放入结构中。然而,我很犹豫是否要这样做,因为我有很多结构需要手动填写。或者,它可以按照这里填写在DllMain中。此外,我应该提到的是,C文件中有extern "C"块。

我尝试了__declspec(dllimport)__declspec(dllexport)extern关键字的不同组合,但我无法使其正确工作。此外,根据从DLL导出全局变量将EXPORT_SYMBOL放入C文件也没有帮助。

这个答案表明我想做的是不可能的,但我不知道它是否只与常量变量相关。

我想做的是不可能的。不能在静态数据的初始值设定项中使用dllimported符号的地址。我通过在每个需要的模块中包含具有结构定义的.c文件来解决这个问题。当以这种方式实现时,结构本身可以保持extern。因此,关于我的代码示例,它看起来是这样的:

file1.c:

#include <file1.h>
#include <file2.h>
#include <file2.c>
structure1_t struct1 = {
&struct2
};

file1.h:

typedef struct
{
structure2_t* ptr;
} structure1_t;
extern structure1_t struct1;

file2.h:

typedef struct
{
int* i;
} structure2_t;
extern structure2_t struct2;

file2.c:

#include <file2.h>
int i;
structure2_t struct2 = {
&i
};

(为便于说明,尚未对其进行测试(。这样,实际上就不会在DLL之间共享任何数据,因为每个DLL都有自己的副本。如果数据必须保留在单独的DLL中,或者如果无法包含.c文件,则其他解决方案是根本不具有初始化器,使用__declspec()而不是extern,并在函数调用中初始化结构。然而,我选择不这样做,因为我有数百个结构,这样做是不可行的。

最新更新