的我想要实现
我工作的动态加载的DLL以插件的程序长的故事。我正在使用Microsoft Visual C++ 2008编译该程序。但是,让我们假设应该支持任何与Qt一起工作的Visual C++版本。该项目目录布局如下:C++:从不同的目录舱单及动态加载的DLL
| plugins/
| plugin1.dll
| plugin2.dll
| QtCore4.dll
| QtGui4.dll
| program.exe
program.exe
发现所有的插件DLL文件,对它们进行调用LoadLibrary(),并调用某个签名功能,以找出是否它实际上是一个插件或没有。对于安装有MSVC90的vcredist的计算机,此功能非常有效。当然,为了使程序在所有计算机上都能正常工作,我必须使用msvc * .dll文件和相应的清单文件来重新分发它。 Qt DLLs还需要redist才能运行。
现在,我已经设置cmake根据选定的Visual Studio版本自动复制适当的redist dll和清单。为了简单起见,我们假设我正在使用MSVC90。当REDIST被复制到程序目录布局如下:
| plugins/
| plugin1.dll
| plugin2.dll
| QtCore4.dll
| QtGui4.dll
| msvcm90.dll
| msvcp90.dll
| msvcr90.dll
| Microsoft.VC90.CRT.manifest (I'm also aware that this file is bugged in VS2008)
| program.exe
关于清单文件中的错误:http://www.cmake.org/pipermail/cmake/2008-September/023822.html
问题
用这个布局的计划目前适用于没有安装redist的电脑,但是插件没有被加载。为了让插件加载,我必须执行以下操作之一:
- 将清单文件复制到
plugins/
目录。从清单文件中删除对msvc * .dll文件的所有引用。这可行,但它不好,因为我必须支持不同版本的编辑清单文件,具体取决于所使用的MSVC的版本。此外,我不知道这是否会与2008年以外的Visual Studio打破。 - 将整个redist复制到
plugins/
目录。这不需要对清单文件进行任何修改,但现在program.exe
愚蠢地尝试加载msvc * .dll文件,认为它们是插件。很自然地,这会失败,所以不会有太大的伤害。另一个缺点是程序包的大小增长超过1MB。不过,这两个问题都是我可以接受的。 - 使用/ MT开关编译插件。简短的测试表明,这实际上有效,但如果Qt和
program.exe
都是/ MD,我不确定它将来会不会破坏任何东西。
的问题(S)
什么是最好的解决方案?什么是正确的解决方案?如果有多个正确的解决方案,那么哪一个是最佳实践?我是第一个尝试这样做的人吗?
更新1(2012年11月18日)
虽然这个问题仍然没有答案,我决定去引起头痛最少的路线。到目前为止,我一直在使用第一号解决方案,并决定坚持使用它。如果CMake检测到用户正在使用与2008不同的MSVC版本,则会显示一条警告消息,指出自动打包不完全受支持。
为什么不静态链接你的应用程序和插件的运行时? –
Qt已经需要vcredist,所以我必须包含它。此外,当资源分配在一个静态链接的实体中,然后在另一个实体链接中释放时,会出现资源分配问题 - 这是不安全的,程序可能会崩溃。我不知道如果Qt是/ MD,这将如何与Qt相互作用。 – ZalewaPL
我想你应该让插件的作者决定他们想如何链接到运行时库,而不是试图强制他们动态链接到特定版本的运行时。 至于你提到的分配问题,如果你调用插件来分配资源,那么你应该回到插件来释放资源。 –