在 Windows 上多次加载具有依赖项的 DLL 库

Load DLL Library with dependencies multiple times on Windows

提问人:molnarriso 提问时间:3/28/2023 更新时间:3/29/2023 访问量:259

问:

想象一下以下场景:

My Program -> lib A -> lib B -> lib C 

我有我的库 A,它加载库 B,它加载库 C。我有源代码,可以修改库 A,但我不能修改库 B 和 C。 库 C 有一个问题:它包含一个单例,它提供了我需要的功能(与设备的网络连接)。但是,如果我想一次连接到更多设备,我不能,因为该库不是为它制作的。

当我生成多个进程时,每个进程都有自己的 A.DLL 句柄,一切正常(我从一台机器并发连接到多个设备)。但是,我想从一个进程连接到多个设备,因为我的程序和我的库 A 之间需要通信,而且我不想通过昂贵的进程间通信来解决它(尽管它应该是可能的,只是缓慢而复杂)。

我发现,如果DLL位于不同的地方,Windows会多次加载DLL。所以我将我的库复制到两个目录中,libs1 和 libs2。然后我加载 libs1/A.DLL 和 libs2/A.DLL。当我检查进程资源管理器时,我看到 A.DLL 实际上加载了两次,这很棒。我试图解决的主要问题是,当我加载第二个 A.DLL 时,Windows 不会从第二个目录再次加载 B.DLL 和 C.DLL,因为它们已经加载。我需要多个 C.DLL 实例。

为了从我的程序加载我的 .DLL 库,我使用 LoadLibrary() 和 SetDllDirectory() 强制 Windows 查看 libs1/libs2 文件夹。

C++ Windows WinAPI DLL 加载库

评论

0赞 Remy Lebeau 3/28/2023
由于 和 是隐式加载的,因此它们仅按系统搜索路径上的文件名加载,而不是按完整路径加载,这就是为什么它们只加载一次的原因,因为文件名已经加载。您可能需要使用并行程序集清单,以便每个副本都可以指定对其本地副本的显式依赖关系,以便它们可以与其他副本分开加载。B.DLLC.DLLA.DLLB.DLLC.DLL
0赞 molnarriso 3/28/2023
我问了ChatGPT,它推荐了同样的东西,我会尝试一下
1赞 IInspectable 3/29/2023
如果可能的话,我会避免这样做。您可以让系统为您启动 DLL 代理项。将所有内容包装在 COM 接口后面,并让 midl.exe 为您生成代理。

答:

0赞 273K 3/28/2023 #1

所有三个 A.DLL、B.Dll 和 C.DLL 都应位于不同的位置。每次加载 A.DLL 时,请在 SetDllDirectory() 中指定此不同的位置。