6

在 Windows 下,我正在尝试使用SomeLib.dllPython 2.7 中用 C++ 编写的第 3 方 DLL (),使用ctypes. 对于它的一些特性,这个库使用另一个 COM DLL ( SomeCOMlib.dll),它本身使用另一个 DLL ( LibA.dll)。

请注意,这不是直接从 Python 使用 COM DLL,而是使用从 Python 使用它的 DLL。

为了使与 Python 的集成更容易,我将要使用的调用分组到我自己的函数中,在一个新的MyLib.dllDLL (情景)。本质上,我的库公开了 2 个函数:, (全部返回,无参数)。ctypesextern "C"doSomethingSimple()doSomethingWithCOMobj()void

“有效”的依赖层次结构如下:

MyLib.dll
  SomeLib.dll
    SomeCOMlib.dll
      LibA.dll

我能够编写一个简单的 C++ 控制台应用程序 (Visual C++),它MyLib.dll可以毫无问题地使用并进行这两个连续调用。

使用 Python/ctypes,第一个调用可以正常工作,但是使用 COM 的调用会抛出WindowsError: [Error -529697949] Windows Error 0xE06D7363. 从库的其余行为中,我可以看到问题正是在进行 COM 调用的地方。

(如果丢失,简单的测试 C++ 应用程序也会或多或少在同一个地方LibA.dll失败,但我不确定它是否相关。)

我已经使用Dependency Walker查看了依赖层次结构。 SomeCOMlib.dll没有列为 的依赖项SomeLib.dll,尽管它显然是必需的,LibA.dll也没有列为 的依赖项SomeCOMlib.dll,尽管它在运行时也明确需要。

我从命令行运行所有内容,从这些 DLL 所在的目录中运行(并且 C++ 示例可执行文件工作正常)。我试图强制 PATH 包含该目录,并且我还尝试将 DLL 复制到我猜想它们可能会被拾取的各个地方(C:\Windows\System32C:\Python27\DLLs),但没有成功。 SomeCOMlib.dll也注册了regasm.exe

ctypes当涉及到它自己对 COM 机制的使用(以及可能随后在那里加载其他 DLL)时,在普通 C++ 应用程序和 Python 应用程序中使用这个 DLL 会导致这种差异?

哪些步骤至少比Windows Error 0xE06D7363Python 提供更多信息,以便能够进一步调查问题?

Python 代码如下所示:

import ctypes
myDll = ctypes.WinDLL("MyLib.dll")
myDll.doSomethingSimple()
myDll.doSomethingWithCOMobj() # This statement throws the Windows Error

(链接到的测试 C++ 独立应用程序在 . 中MyLib.dll进行完全相同的调用main。)

4

3 回答 3

5

当您需要一个进程内 COM 对象时,您不需要直接链接到实现的 DLL。您通常使用CoCreateInstance/ CoCreateInstanceEx,它将为您加载 DLL。

查找通过应用程序的清单及其依赖程序集清单。这样做是为了支持免注册 COM

如果没有应用程序清单,或者没有任何依赖程序集清单在comClassXML 元素中声明您的类,则查找默认为注册表,它将检查1以查找名为的子项,该子项本身带有一个说明 DLL 的子项。HKEY_CLASSES_ROOT\CLSID{<your-CLSID>}InProcServer32

这解释了为什么 SomeCOMlib.dll 不显示为依赖项。它没有解释为什么 LibA.dll 不作为它的依赖项出现,可能是因为它是动态加载的。如果您在 Dependency Walker 中分析您的应用程序,您将在底部窗格中看到 LoadLibrary 调用的日志。要对其进行分析,请在 Dependency Walker 中打开您的 Python 可执行文件,然后转到菜单选项 Profile->Start profiling...,设置参数以运行您的.py文件,然后单击 Ok。

0xE06D7363 异常代码是Visual C++ 异常代码。您应该检查doSomethingWithCOMobj. 要调试它,请使用您喜欢的工具(Visual C++、WinDbg 等),打开 Python 的可执行文件,设置运行.py文件的参数,并在运行应用程序之前在函数的第一条语句上启用断点。然后运行它并逐步执行每条指令。

很难猜测您的本机 C++ 应用程序和 Python 有什么不同,但可能是 Python 和 使用了不同的 COM 初始化参数doSomethingWithCOMobj,或者您没有声明它__stdcall(尽管是一个无关紧要的 void 函数) ,或者它尝试写入标准输出并且您使用pythonw.exe的不是控制台应用程序等。


1. HKEY_CLASSES_ROOT是和的混合HKEY_CURRENT_USER\Software\ClassesHKEY_LOCAL_MACHINE\Software\Classes

于 2012-11-16T20:12:31.870 回答
2

您可以使用诸如 processexplorer 之类的东西来确定是否所有必需的库都已加载到正在运行的进程中。

  1. 您是否在 Python 代码中的某处初始化了 COM 运行时?在您的 C++ 代码中?C++ 代码和 Python/ctypes 之间的一个区别是,在 C++ 代码中,dll 的 DllMain() 函数在加载 dll 时被调用,Python/ctypes 不会这样做,因为 dll 是完全动态加载的。
于 2012-11-14T17:30:40.133 回答
1

我猜你有和我一样的问题,虽然我真的不知道,因为与这种情况不同,我对我正在使用的 dll 一无所知。6年后我不知道你是否还能测试这个,但我想知道导入pythoncom是否能解决问题。

import ctypes
import pythoncom
myDll = ctypes.WinDLL("MyLib.dll")
myDll.doSomethingSimple()
myDll.doSomethingWithCOMobj() # This statement throws the Windows Error
于 2018-03-14T01:47:23.900 回答