使用COM对象的Python ctypes和DLL

2024-04-25 07:11:16 发布

您现在位置:Python中文网/ 问答频道 /正文

< Windows >下,我尝试使用Python 2.7中使用^ {CD2>}编程C++中的第三方DLL(^ {CD1>})。 对于它的一些特性,这个库使用另一个COM DLL(SomeCOMlib.dll),它本身使用另一个DLL(LibA.dll)。在

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

< >为了使Python的集成更容易,我将我要使用的调用分组到一个新的DLL(^ {CD5>})中,也用C++编程,只需使^ {}的调用更方便(使用^ {CD7>},并为特定场景定制函数)。 实际上,我的库公开了2个函数:doSomethingSimple()doSomethingWithCOMobj()(全部返回void,没有参数)。在

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

MyLib.dll
  SomeLib.dll
    SomeCOMlib.dll
      LibA.dll
<>我能编写一个简单的C++控制台应用程序(Visual C++),使用^ {CD5>},连续2次调用都没有问题。在

使用Python/ctypes,第一个调用可以正常工作,但是使用COM的调用抛出一个WindowsError: [Error -529697949] Windows Error 0xE06D7363。 从库的其他行为中,我可以看到问题就发生在COM调用的位置。在

(简单测试C++应用程序也会在相同的地方失败,如果^ {CD4}}丢失,但我不确定它是否相关)

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

< >我从命令行运行所有的东西,从这些DLL目录中(C++示例可执行文件工作得很好)。 我试图强制路径包含该目录,还尝试将dll复制到我猜想可能会被拾取的地方(C:\Windows\System32和{}),但没有成功。 SomeCOMlib.dll也在{}注册。在

<> p><强> >在使用COM机制(可能还有后续加载其他DLL)时,使用这种DLL从普通C++应用程序和Python的^ {CD2>}会造成什么区别?

哪些步骤比Python中的Windows Error 0xE06D7363提供更多的信息,以便能够进一步研究问题?

Python代码如下所示:

^{pr2}$

(测试的C++独立应用程序,链接到^ {CD5>}在^ {CD25>}中调用完全相同)


Tags: 函数com应用程序层次结构关系windows编程error
3条回答

您可以使用类似processexplorer的工具来确定是否所有必需的库都加载到正在运行的进程中。在

  1. 你在Python代码中初始化了COM运行时吗?在C++代码中? C++代码和Python/Cype之间的一个区别是,在C++代码中,当DLL被加载时,DLL的DLLIN主()函数被调用,Python/Cype不会因为DLL的完全动态加载而这样做。在

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

查找通过application's manifest及其依赖项{a4}。这样做是为了支持registration-free COM。在

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

这就解释了为什么SomeCOMlib.dll不显示为依赖项。它不能解释为什么图书馆.dll不会显示为它的依赖项,可能是因为它是动态加载的。如果您在Dependency Walker中评测应用程序,您将在底部窗格中看到LoadLibrary调用的日志。要对其进行评测,请在Dependency Walker中打开Python可执行文件,然后转到菜单选项“profile->Start profiling…”,设置运行.py文件的参数,然后单击“确定”。在

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

很难猜测你的本地C++应用程序和Python有什么不同,但是可能是不同的COM初始化参数被Python和^ {CD8>}使用,或者你还没有声明它^ {CD11>}(虽然是一个不重要的空洞函数),或者它试图写入stdout,而您使用的不是控制台应用程序的pythonw.exe,等等


1.HKEY_CLASSES_ROOTHKEY_CURRENT_USER\Software\Classes和{}的混合体。在

我将猜测您拥有same issue that I had,尽管我不太清楚,因为与本例不同,我对所使用的dll一无所知。6年后,我不知道你是否还能测试这个,但是我想知道导入pythoncom是否能解决这个问题。在

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

相关问题 更多 >