2

对不起,如果这个问题之前已经回答过;然而,所有类似的问题似乎都与 DLL 中的全局或静态变量以及这些变量的共享有关。

是否可以在两个单独的应用程序之间共享一个 dll 实例?

我有两个应用程序(appA、appB)和一个 DLL(theDLL)。

我正在查看 appA 是否可以调用 DLL 中的函数,然后在堆上创建一个变量并将其存储在 DLL 中。稍后,我想让 appB 连接到 DLL 并能够访问之前创建的变量。再次抱歉,如果此答案与 dll 中的静态和全局变量相同。

这是一些伪代码:

(DLL)

class VariableHolder
{
 public:
     void StoreVariable(int x)
     {
        mInt = new int(x);
     }

     int GetVariable()
     {
        return mInt;
     }
 private:
     int mInt;
}

(appA)

int main()
{
    ...
    (assuming we got access to a VariableHolder singleton created in theDLL)
    theVarialbeHolder.StoreVariable(5);
    ... 
}

(应用程序B)

int main()
{
    ...
    (assuming we got access to a VariableHolder singleton created in theDLL)
    if (theVarialbeHolder.GetVariable() == 5)
    {
        cout << "Hurray, how did you know?";
    }
    ... 
}
4

6 回答 6

3

这完全是不可能的——因为两个进程的地址空间不同(因为它们是虚拟的,由内核创建),所以一个有效的指针在另一个中不起作用。但是,您可以使用共享内存在进程之间传输原始标量数据(字符串、整数)——方法如下。

于 2012-08-15T05:28:09.860 回答
3

是的,这可以使用共享内存。不过,它不需要使用共享 DLL。

根据操作,方法有些不同:

  • 在 Windows 上,共享文件用于映射到内存中(请参阅创建命名共享内存)。

  • 在 Linux 和 Unix 上,有创建共享内存区域的直接函数,例如 System V IPC。只是谷歌它。

于 2012-08-15T05:50:58.967 回答
3

几乎所有现代操作系统上的共享库都是由共享只读可执行文件和数据页实现的,同时映射到使用给定库的任何进程的地址空间。但在 Windows 上(与大多数 Unix 系统相比),这种共享也可以扩展到 DLL 中的读写数据段,因此可以在 DLL 中拥有全局变量,在所有加载了 DLL 的图像之间共享。为了实现这一点,涉及一个两步过程。首先,您告诉编译器将共享变量放在一个新的命名数据段中:

#pragma data_seg (".myshared")
int iscalar = 0;
int iarray[10] = { 0 };
#pragma data_seg ()

将所有这些变量静态初始化很重要,否则它们将最终进入该.bss部分。然后您必须告诉链接器您希望使用该选项拥有.myshared具有共享读写属性的部分。/SECTION:.myshared,RWS

这种机制比创建和绑定到命名的共享内存对象要简单得多,但它只允许共享静态分配的全局变量——你不能使用它来共享堆上的数据,因为堆是进程私有的。对于任何更复杂的事情,您应该使用共享内存映射,即如 MSDN 页面上所示,在 H2CO3 的答案中链接。

于 2012-08-16T08:29:52.193 回答
1

这是不可能的。DLL 可以在 2 进程中共享,但数据不是。共享的是代码或程序映像(即逻辑或指令),而不是数据。每个 Dll 都映射到加载它的进程的虚拟地址空间,因此数据要么在进程的数据部分上,要么在函数本地的堆栈上。当一个进程正在执行时,其他进程数据的地址是不可见的。

您需要阅读虚拟内存以及内存管理单元 (MMU) 的工作原理。操作系统、CPU、MMU 协同工作使之成​​为可能。可靠的方法是进程间通信。您可以使用共享内存,其中每个进程都有一个虚拟地址形式的数据副本,但它最终映射到实际内存中的相同位置,即实际地址。操作系统使之成为可能。

于 2012-08-15T05:47:35.473 回答
0

正如@H2CO3 指出的那样,由于地址空间不同,这是不可能的。

但是,从您的问题来看,您似乎需要围绕该 DLL 或服务的代理进程,然后不同的进程可以连接到该代理进程/exe 并使用共享内存。

于 2012-08-15T05:31:31.403 回答
0

您必须使用共享内存(如上所述)。

我建议使用 boost 进程间库。请参阅有关共享内存的文档 -进程之间的共享内存

于 2012-08-15T06:01:18.447 回答