在 DLL 之间共享数据

Posted

技术标签:

【中文标题】在 DLL 之间共享数据【英文标题】:Sharing data between DLLs 【发布时间】:2015-03-15 22:49:29 【问题描述】:

我正在研究 MSVC++ 2012 中的一个项目,我正在尝试将其拆分为更小的部分。目前,依赖项看起来像这样:

output.exe --- deploy.dll --- coreext.dll
                          |
                          |-- physical.dll --- coreext.dll
                          |
                          |-- renderer.dll --- physical.dll --- coreext.dll
                          |                |
                          |                |-- coreext.dll
                          |
                          |-- engine.dll ----- physical.dll --- coreext.dll
                                           |
                                           |-- coreext.dll

我有一些全局数据在“physical.dll”中发生了变化,但似乎这种变化并不适用于 physical.dll 的所有实例。该值在“deploy.dll”级别更改,但在“engine.dll”级别不更改。目前,我正在使用隐式链接。实际输出中还有三层依赖关系,但我现在只是在处理这些部分。

对于我的一生,我似乎也无法弄清楚如何将数据传递到适当的级别。我在 renderer.dll 和 engine.dll 中放置了一个函数来设置全局数据,但是当与调试器逐行运行时,它一旦进入就不是一个有效的指针——可能是一些虚拟地址的东西?

我看到了this,这让我觉得这应该不是问题。然后this 带我到this,我正在阅读它并试图将其包裹起来。这是我第一次在 Windows 中执行此操作,我感觉我正在接近这种设计完全错误。

我不想做大量的 dumpbin 和 GetProcAddress(),因为有数千个函数要处理,维护起来会很痛苦(但我想仍然是可自动化的)而且代码无处可去一样干净。除了将我所有的 DLL 更改为 OBJ 文件的集合并链接这些文件 - 这可行,但让我回到原来的位置 - 我怎样才能让它工作?

【问题讨论】:

进程中的任何 DLL 都只有一个实例。 我是这么想的,但是在逐步调试中从 DLL 跳转到 DLL 时数据的变化告诉我不是这样。我怎么会搞砸呢? 您确定您没有错误地拥有多个 变量 副本 - 例如每个 DLL 中的一个副本? (如果您忘记使用 dllimport/dllexport 可能会发生这种情况) 可能就是这样。现在我把它作为一个类内部的私有静态变量来存储一个实例,以及一个公共静态函数来检索该实例。我在导出变量本身时遇到了一些严重的链接器问题,但我会再试一次。 【参考方案1】:

只有程序的进程和线程才有自己的生命和数据。

DLL 只是将一些相同的定义放在不同的文件中的技术手段,而不是像往常一样将它们放在可执行文件中。所以他们没有自己的数据。顺便说一句,虽然您的程序可能会加载多个实例(每个实例都有自己独立的状态和全局变量),但只有一个 DLL 可以是loaded once。

因此,您显示的不是 DLL 的多个实例,而是同一个 DLL 的多个依赖项(除非您有不同版本的 DLL)。

DLL 的内容、代码和数据被映射到调用进程的地址空间。因此,DLL 中的全局变量确实是您程序的全局变量。 DLL 不能有自己的。最终,使用相同 DLL 在进程之间共享数据是可能的,但需要创建共享数据段,如this MSDN article 中所述。

但是,从您的症状来看,您可能多次定义全局数据(例如:标题中的静态定义,或使用匿名命名空间的标题中的全局定义)。在这种情况下,您会认为您总是引用同一个全局变量,但每个 .obj 和每个 .dll 都将使用自己的副本。

【讨论】:

这是有道理的。我将如何使单独的部分引用相同的静态变量?我已经在变量上仔细检查了我的 dllexport/dllimport。如果它是用于构建physical.dll的变量上的dllexport和用于构建engine.dll的变量上的dllimport,那么在physical.dll内部进行实例化并不重要,对吗? 看起来确实正确。但它是静态类成员还是静态全局?您能否展示它是如何在标头中声明的以及它是如何实例化的(包括命名空间上下文,如果有的话)?

以上是关于在 DLL 之间共享数据的主要内容,如果未能解决你的问题,请参考以下文章

dll之间共享数据

dll之间共享数据

dll之间共享数据

dll之间共享数据

.exe 和 .dll 之间的共享配置

VC 利用DLL共享区间在进程间共享数据及进程间广播消息