代码之家  ›  专栏  ›  技术社区  ›  kshahar

我可以在同一进程中使用同一DLL的两个不兼容版本吗?

  •  11
  • kshahar  · 技术社区  · 16 年前

    我有没有办法在同一个过程中使用这两个库?

    注: LoadLibrary无法解决此问题,因为我的进程不是导入供应商文件的进程。

    编辑: 忘了提及显而易见的一点,我不必为任何商业库编写源代码,而且可能永远也不会( ).

    编辑: 顺便说一句,另一种方法是: How to combine GUI applications in Windows

    7 回复  |  直到 7 年前
        1
  •  5
  •   Rob Kennedy    16 年前

    我认为你最有希望的选择是大声向销售互不兼容产品的供应商投诉。这与DLL的想法相反。

    你不能把DLL放在不同的目录中。加载具有给定名称的DLL后,加载具有相同模块名称的另一个DLL的所有其他尝试都将使用已加载的DLL,即使路径不同。

        2
  •  5
  •   cdiggins    12 年前

    我也有类似的问题。具体来说,我想使用一个Python解释器中的PyQt,该解释器嵌入在使用不兼容版本的Qt的应用程序中。主应用程序使用了两个Qt dll:QtCore.dll和QtGui.dll。

    当我从嵌入式Python解释器加载PyQt时,我会得到一个错误:

    ImportError: DLL load failed: The specified procedure could not be found.
    

    这发生在以下行:

    from PyQt4 import QtGui
    

    问题在于,一旦不兼容的QtGui.dll加载到主应用程序的进程空间中,对QtGui.dll的任何引用(例如,从文件QtGui.pyd)都是不正确的。

    接下来发生了什么,我并不自豪。

    首先我改名了 QtGui4.dll QtGuiX.dll 然后改名为 QtCore4.dll QtCoreX.dll . 请注意 重命名保持了相同的字符数,这一点很重要。

    接下来我打开了文件 QtGui.pyd 在记事本++中,并替换了所有 QtGui4.dll QtCore4.dll QtCoreX.dll . 我对这些文件重复了这个过程: QtCore.pyd , QtGuiX.dll QtCoreX.dll

    最后,我检查了我的PyQt测试应用程序是否仍然有效。是的!

    因此,它似乎适用于一些琐碎的情况。我希望我 需要对PyQt中的所有DLL和PyD重复此过程

    由于激发了这个可怕的故事,其他人应该受到表扬(或责备)。

        3
  •  4
  •   DarthPingu    16 年前

    正如其他人提到的,您可以重命名VendorLibUtils的一个副本,并修改关联VendorLib DLL的导入表以链接到它,而不是创建它时使用的VendorLibUtils.DLL。

    有一些工具可以让您以这种方式编辑EXE/DLL文件。 CFF Explorer

    当然,这假设VendorLib使用导入表来访问VendorLibUtils,但它可能不使用 LoadLibrary / GetProcAddress ,在这种情况下,您将不会看到VendorLibUtils的导入表条目。

    实际上,如果VendorLib确实使用导入表,但是 而且 使用 加载 要在某些地方访问VendorLibUtils DLL(我已经看到了),这些地方仍然会使用错误的DLL。如果重命名这两个库,在这种情况下至少可能会看到一个错误(因为现在不存在具有原始名称的DLL)。如果发生这种情况,有一种方法可以解决,但在这一点上它开始变得非常复杂,所以除非你真的想/需要知道,否则我不会详细说明。

        4
  •  3
  •   activout.se    16 年前

    LoadLibrary

    X

    如果VendorLibUtils DLL具有一个或多个具有相同名称的导出符号,则 可以

        5
  •  2
  •   Andreas Magnusson    16 年前

    我不是DLL方面的专家,但我认为唯一可行的方法是使用 LoadLibrary() 并显式加载DLL。然后,您可以使用 GetProcAddress()

    HMODULE v1 = LoadLibrary(_T("libv1_0.dll"));
    libv1_0::fun_in_lib = reinterpret_cast<FUNTYPE>(GetProcAddress(v1, _T("fun_in_lib"));
    

    HMODULE v2 = LoadLibrary(_T("libv2_0.dll"));
    libv2_0::fun_in_lib = reinterpret_cast<FUNTYPE>(GetProcAddress(v2, _T("fun_in_lib"));
    

        6
  •  1
  •   MSalters    16 年前

    您的意思是,您的情况与MSVCRT80.DLL和MSVCRT90.DLL类似?微软对这些DLL进行编号有一个很好的理由。如果这两个DLL都被称为MSVCRT.DLL,那么在单个进程中只能加载其中一个DLL。

        7
  •  0
  •   Chris Becke    13 年前

    实际上,可以将不同版本的dll隐式加载到单个进程中。

    1. 创建两个程序集,每个程序集包含必须多次加载的dll版本。听起来很复杂,但实际上它只需要创建(2)个命名的子文件夹,每个子文件夹都有一个包含一些xml的.manifest文件和它自己的dll副本。因此,VendorUtilsAssemblyV1和VendorUtilsAssemblyV2

    2. 通过添加明确标识VendorUtilsAssemblyV1或V2的assemblyDependency指令,使每个依赖dll使用汇编机制来解析隐式依赖关系。

    如果它们已经包含清单(可能链接到VS2005或VS2008 C-Runtime),则使用MT.EXE工具合并到新的依赖项中。