在Visual Studio中使用.def代替全局变量的dllimport/dllexport

Using a .def in Visual Studio instead of dllimport/dllexport with global variables

本文关键字:全局变量 dllimport dllexport def Studio Visual      更新时间:2023-10-16

在PluginLoader.exe的main.cpp中:

int Lives = 9;

该项目还包含一个.def文件,用于导出Lives变量(已修改的c++):

EXPORTS
?Lives@@3HA

使用依赖walker,我在打开PluginLoader.exe时验证了?Lives@@3HA确实被导出。还导出了一个.lib,其中应该包含我们可以在其他项目中链接的存根。在stub PluginLoader上使用dumpbin.exe。lib我得到:

4 ?Lives@@3HA
1 __IMPORT_DESCRIPTOR_PluginLoader
2 __NULL_IMPORT_DESCRIPTOR
4 __imp_?Lives@@3HA
3 ⌂PluginLoader_NULL_THUNK_DATA

PluginLoader正在使用LoadLibrary/GetProcAddress加载SimplePlugin.dll。SimplePlugin.dll有一个main.cpp,看起来像这样:

extern int Lives;
extern "C" __declspec(dllexport) void PluginMain()
{
  ++Lives;
}

SimplePlugin也链接到存根PluginLoader.lib。当尝试增加生命时,我总是因为ACCESS违例而崩溃。看起来我的SimplePlugin.dll是伪获得自己版本的Lives变量,即使它链接到存根。

如果我将ONLY SimplePlugin's Lives更改为:

__declspec(dllimport) extern int Lives;

一切正常。为什么会这样?我认为.def的目的是不必使用dllexport/dllimport。我目前的假设是,具有全局变量的dlimport在幕后做了一些诡计(&Lives如何在dll与exe中工作?)。这和__imp_?Lives@@3HA有关系吗?

注意:不带dllimport的导入函数指针可以正常工作。只有全局变量才会导致崩溃。这在VS 2010和2012中重现

示例项目:https://db.tt/maV0oWop

当您对数据使用dllimport时,编译器确实生成间接代码。

原因是DLL只能导出指向导出数据的指针,而dllimport为您解除对该指针的引用。对于函数指针,显然不需要这样做。

MS docs on the