Visual Studio - 具有相同名称的非托管C++ DLL 在同一进程中共存
visual studio - Unmanaged C++ DLL's with same name coexisting in same process
使用Visual Studio c++V10,我正试图找出如何构建DLL并解决DLL命名冲突。以下是详细信息。
S公司推出了一种名为M.EXE
的产品。假设M.EXE
安装在SBINM.EXE
中。S公司静态链接到一个名为U.DLL
的DLL,该DLL安装在SBINU.DLL
中。U.DLL
包含开源代码,并使用Visual C++编译器选项/Zc:wchar_t-
构建,后者不将wchar识别为本机类型。
公司C提供一个名为O.DLL
的DLL,并发布该DLL的API,并提供O.DLL
的导入库。假设O.DLL
安装在CBINO.DLL
中。O.DLL
静态链接到一个名为U.DLL
的DLL,该DLL安装在CBINU.DLL
中。U.DLL
构建在相同的开源代码上,但使用Visual C++编译器选项/Zc:wchar_t
构建,后者确实将wchar_t
识别为本机类型。
理想情况下,C公司和S公司会同意使用相同的Visual C++选项来构建U.DLL
,但这是不可能的。
S公司的M.EXE
是可扩展的,因为我可以在非托管C++中构建自己的DLL,称之为NODE.DLL
,如果我正确设置了所有内容,M.EXE
将调用它。我想构建NODE.DLL
,使其静态链接到C公司的O.DLL
。但问题是,一旦M.EXE
运行,它就从SBIN
加载了U.DLL
库,并且SBINU.DLL
中的符号与CBINU.DLL
中的符号略有不同,因为每个公司都是如何构建U.DLL
的。因此,当M.EXE
尝试加载NODE.DLL
时,它失败了,因为当NODE.DLL
加载需要U.DLL
的O.DLL
时,CBINU.DLL
所需的符号不存在,因为Windows认为U.DLL
已经加载。
情况示意图如下:
M.EXE static link to -> SBINU.DLL
M.EXE dynamic link to -> NODE.DLL
NODE.DLL static link to O.DLL
O.DLL static link to CBINU.DLL
实际上,我需要SBINU.DLL
和CBINU.DLL
共存于同一进程空间中,并让M.EXE
使用其版本的U.DLL
,O.DLL
使用其版本U.DLL
。
请注意,我没有重建M.EXE
或O.DLL
以更改它们各自加载U.DLL
的方式的选项。它们来自第三方,因此静态链接无法更改。我也没有在O.DLL
上使用LoadLibrary
的选项,因为它是一个C++库,提供了一个导入库。
我相信清单是可以使用的,这样当我构建静态链接到O.DLL的NODE.DLL
时,我会在NODE.DLL
的清单中设置内容,以便O.DLL
加载安装在CBINU.DLL
中的U.DLL
的自己的副本。我就是不知道该怎么做。理想情况下,我不想修改O.DLL
的清单,但如果这是唯一的解决方案,我会接受它。
您可以在同一进程中通过用绝对路径加载一个或多个具有相同文件名的DLL。这确实需要动态加载DLL,但行为在其他方面是相同的。
您需要std::string moduleName = appPath + "sbinu.dll"; LoadModule(moduleName.c_str())
,而不是在构建过程中进行链接。因为这对于需要加载哪个DLL是明确的,所以它允许您加载多个具有"相同"名称的DLL。
一旦加载了模块,就可以将每个必要的函数分配给函数指针,然后将它们包装起来,或者使用合法但很少使用的语法将函数指针作为普通函数调用(funcPtr(params)
(。
如果您使用的是较新版本的Windows,则可以使用DLL清单来加强模块的版本控制/命名,并使EXE加载与通常不同的DLL。我不熟悉具体是如何做到这一点的,尽管MSDN上有相关文档(可能也在这里(。
您可以在运行时使用/delaylod链接器选项(VS项目属性中的linker/Input/Delay Loaded DLL(和自定义挂钩以编程方式解析源DLL。在一个源文件中,您需要定义并注册一个delaylod-hook函数。在钩子函数的dliNotePreLoadLibrary通知处理程序中,只需使用指向所需DLL的显式路径调用LoadLibrary,然后将DLL的HMODULE传递回delaylod代码。delaylod代码将把导入的函数解析到您给它的DLL中,而不管进程中是否已经加载了另一个同名的DLL。
在我的脑海中,你的钩子看起来是这样的(在冲突的情况下,MyCustomLoadLibrary需要用调用LoadLibrary的代码来替换,该代码具有所需DLL的完整路径,否则仅为不合格的文件名(:
#include <delayimp.h>
FARPROC WINAPI MyDliNotifyHook( unsigned dliNotify, PDelayLoadInfo pdli )
{
if( dliNotify == dliNotePreLoadLibrary )
return (FARPROC)MyCustomLoadLibrary( pdli->szDll );
return NULL;
}
extern "C" PfnDliHook __pfnDliNotifyHook2 = MyDliNotifyHook;
尝试使用LoadLibrary和GetProcAddress。这将需要重新构造代码,以便在任何地方都使用函数指针。参见:
LoadLibrary 的MSDN网页
你很幸运U.DLL是开源的。您需要构建一个同时支持/Zc:wchar_t-
和/Zc:wchar_t
函数的版本。第一个选项仅将wchar_t-
定义为unsigned short
。对于每个没有wchar_t
参数的函数,您会收到大量关于重复符号的链接器警告,但否则您只会得到一个更胖的DLL。
请注意,如果有任何全局或static
变量使用wchar_t
,那么您也会有它们的两个副本。但如果你在一个过程中硬塞进两份U.DLL
,也会产生同样的效果。
- 挂起和取消挂起一个文件DLL
- std::threads可以从Windows DLL中的全局变量创建/销毁吗?
- 导入库可以跨dll版本工作吗
- 从C++dll访问C#中的一行主要参数
- 链接到自行创建的dll失败
- 为什么使用 P/Invoke 调用 dll 时,某些计算机中的 LoadLibrary 失败?
- 在调用FreeLibrary后,释放动态链接到具有相同版本的CRT堆的DLL的内存
- 如何指定我希望我的LIB链接到的DLL文件?-Visual Studio 2019
- 如何将图像传输到c++(dll)中的缓冲区,然后在c#的缓冲区中读/写
- C++:将外部库链接到dll库
- 在 Windows 上,是否可以让 dll 在不使用 PATH 环境变量的情况下在另一个文件夹中查找依赖项?
- 不同的Visual Studio版本中缺少.dll
- 从DLL中删除类的实例
- 如何包装第三方DLL在R中使用
- 使用c#访问c++dll中带有char*参数的函数时发生AccessViolationException
- 系统.将数组移交给c#中动态加载的c++DLL时发生AccessViolationException
- 为什么导入Mixed native/CLR lib.dll的本机C++应用程序没有在Mixed lib.dll中的外部变
- 当我使用 C++ 中的 C# dll 来使用 Selenium 时,存在异常处理问题
- Python ctypes:不会按预期加载 dll
- 在 C++/CLI 中将 .NET 事件从一个 DLL 引发到另一个 DLL