Bru*_*uno 6 python com dll ctypes
在Windows下,我正在尝试使用SomeLib.dllPython 2.7中用C++编写的第三方DLL()ctypes.对于它的一些功能,这个库使用另一个COM DLL(SomeCOMlib.dll),它本身使用其他DLL(LibA.dll).
请注意,这不是直接从Python使用COM DLL,而是使用从Python使用它的DLL.
为了更容易地与Python集成,我将我想要用于我自己的函数的调用分组到一个新的DLL(MyLib.dll)中,也用C++编程,只是为了使调用ctypes更方便(使用extern "C"和定制特定的函数)场景).从本质上讲,我的库公开2个功能:doSomethingSimple(),doSomethingWithCOMobj()(全部返回void,没有参数).
"有效"依赖关系层次结构如下:
MyLib.dll
SomeLib.dll
SomeCOMlib.dll
LibA.dll
Run Code Online (Sandbox Code Playgroud)
我能够编写一个简单的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\System32和C:\Python27\DLLs)的各个地方,但没有成功.
SomeCOMlib.dll也注册了regasm.exe.
什么可能导致从普通的C++应用程序和Python的使用此DLL之间的差异,ctypes当涉及它自己的COM机制的使用(以及可能后续加载其他DLL)?
哪些步骤至少可以提供比Windows Error 0xE06D7363Python 更多的信息,以便能够进一步调查问题?
Python代码如下所示:
import ctypes
myDll = ctypes.WinDLL("MyLib.dll")
myDll.doSomethingSimple()
myDll.doSomethingWithCOMobj() # This statement throws the Windows Error
Run Code Online (Sandbox Code Playgroud)
(工作的测试C++独立应用程序,链接到MyLib.dll内部完全相同的调用main.)
当您需要一个进程内 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(尽管是一个无效的函数,应该无关紧要) ,或者它尝试写入标准输出而您使用pythonw.exe的不是控制台应用程序等。
1. HKEY_CLASSES_ROOT是的混合HKEY_CURRENT_USER\Software\Classes和HKEY_LOCAL_MACHINE\Software\Classes。
您可以使用 processexplorer 之类的工具来查明是否所有必需的库都已加载到正在运行的进程中。