首先,有一些类似的问题,但没有一个真正解决确切的问题:
所以,这就是我的问题:我正在开发一个VST插件,我有一个在DLL中定义和实现的类。加载了同一个DLL的多个实例,我想要做的是保持"实例计数"监视类的构造次数(当按照VST标准加载DLL时,它只发生一次。)
这样做的一种简单方法是创建一个类静态变量,我将其初始化为0并在析构函数中的构造函数/减量中递增。我确信我知道什么时候构建和销毁我的类,但我不确定的是这个类静态变量是否会在我的DLL实例之间共享。
为了澄清,我多次加载相同的DLL; DLL中是一个类(仅在DLL代码中使用,而不是暴露给应用程序。)关于DLL中定义的数据行为是否因Windows和Unix之间的不同而有所讨论,所以我喜欢要知道在DLL中执行此类操作对于跨平台使用是否安全。
在DLL中定义的示例类,不以任何方式暴露给加载DLL的应用程序(或其他方式。)
标头文件
// Foo.h
# pragma once
class Foo {
static int s_InstanceCount;
public:
Foo();
~Foo();
};
现在是源文件
// Foo.cpp
#include "Foo.h"
int Foo::s_InstanceCount = 0;
Foo::Foo() {
s_InstanceCount++;
}
Foo::~Foo() {
s_InstanceCount--;
if (s_InstanceCount == 0) {
// Do something
}
}
Foo的构造函数仅在应用程序加载DLL时调用(即Windows上的:: LoadLibrary),并且仅在释放DLL时调用析构函数(即Windows上的FreeLibrary)。考虑到保证。是否会在对构造函数的调用之间共享s_InstanceCount?
编辑: 正如Serge在下面指出的那样,一个进程无法真正加载DLL两次。因此,当我的DLL被一个进程加载两次时,构造的Foo实例存在于加载过程使用的相同内存空间中。也许...
答案 0 :(得分:4)
DLL只是在调用它的进程的地址空间中运行的共享代码。每个进程都获得自己的DLL中定义的全局/静态变量的副本。
This article向您解释。但它也提供了一个很好的解决方法,可以使用file mapping在多个进程中共享数据。这可以帮助您解决问题。
编辑: 显然有另一种解决方案,创建一个共享数据段(即告诉链接器共享一些数据,就像它对代码一样)。这里microsoft doc和proof of concept on codeproject。我从来没有使用它,所以它仍然需要测试它是否适用于静态类成员。
答案 1 :(得分:1)
不,您示例中的s_InstanceCount
将对DLL的每个实例都是私有的。此外,如果不调整DLL的文件名,通常无法在同一进程中多次加载它,如下所述:Load the same dll multiple times。
如果DLL实例在您的情况下处于不同的进程中,那么您需要进程间通信,例如通过shared memory。