gpt4 book ai didi

python - 如何从 python 中的 dll 加载带有自定义接口(interface)的 COM 对象?

转载 作者:太空宇宙 更新时间:2023-11-04 05:05:13 28 4
gpt4 key购买 nike

大家好。任务是使用从 dll 加载的 COM 对象(禁止使用 regsvr32)。此外,该对象公开了我将来需要的 DirectShow 接口(interface)。

然后我尝试使用 this link 中的示例获取模块,我遇到了一个问题:pythoncom 对 DirectShow 接口(interface)一无所知(例如 IBaseFilter)。和 from this post我的印象是 pythoncom 不支持自定义 COM 接口(interface),但那是在 2008 年,也许现在情况有所改变?

代码是

# -*- coding: utf-8 -*-
import ctypes, inspect, os, pythoncom, sys
from comtypes import client
from ctypes import OleDLL, c_long, byref
from uuid import UUID

#dshow is a module with DirectShow constants, etc
cmd_subfolder = os.path.realpath(os.path.abspath(os.path.join(os.path.split(inspect.getfile( inspect.currentframe() ))[0],"path_to_dshow_module")))
if cmd_subfolder not in sys.path:
sys.path.insert(0, cmd_subfolder)
import dshow

#that way comtypes gets to know about DirectShow interfaces
qedit = client.GetModule("qedit.dll")
dll_path = os.path.join(cmd_subfolder, "../my_path/my_dshow_filter.ax") #specifying path to dll
iid_interface = dshow.CLSID_IUnknown
iid_ibasefilter = dshow.CLSID_IBaseFilter
clsid_class = UUID(dshow.CLSID_my_filter).bytes_le
iclassfactory = UUID(str(pythoncom.IID_IClassFactory)).bytes_le
com_classfactory = c_long(0)

my_dll = ctypes.oledll.LoadLibrary(dll_path)
#getting com_classfactory pointer to an adress of IClassFactory within loaded dll
hr = my_dll.DllGetClassObject(clsid_class, iclassfactory, byref(com_classfactory))
#creating class factory from adress using pythoncom
MyFactory = pythoncom.ObjectFromAddress(com_classfactory.value, pythoncom.IID_IClassFactory)
#creating COM object using IClassFactory::CreateInstance, using IUnknown as a default interface
dmx_interface = MyFactory.CreateInstance(None, iid_interface)
# I could've tried to use IBaseFilter directly,
# but pythoncom knows nothing about DirectShow interfaces!
# dmx = dmx_interface.QueryInterface(str(qedit.IBaseFilter._iid_)) #that yields an error
dmx = dmx_interface.QueryInterface(iid_ibasefilter) #that yields the same error

我得到的错误是TypeError: There is no interface object registered that supports this IID,这是可以理解的。

所以,comtypes 知道这些接口(interface)!但不幸的是,我找不到使用 comtypes 甚至 ctypes 从 dll 加载 COM 对象的方法。

我已经处理这个问题好几天了,非常感谢您的建议。

最佳答案

最后,它需要一些指针操作,但我做到了。

我从 comtypes.server 导入了类 IClassFactory 并为它获取了一个指针(指针 №1)。之后,我获得了一个指向我加载的 dll 中的 IClassFactory 对象的 c_long 指针(指针 №2)。最后,我将指针 №2 的值赋给了指针 №1。

from comtypes.server import IClassFactory
#same code as it was before
dll_path = os.path.join(cmd_subfolder, "../my_path/my_dshow_filter.ax")
clsid_class = UUID(dshow.CLSID_my_filter).bytes_le
#that may be replaced with other IID_IClassFactory definition
#so no pythoncom is required at all
iclassfactory = UUID(str(pythoncom.IID_IClassFactory)).bytes_le
com_classfactory = c_long(0)
my_dll = ctypes.oledll.LoadLibrary(dll)
hr = my_dll.DllGetClassObject(clsid_class, iclassfactory, byref(com_classfactory))
ptr_icf = POINTER(IClassFactory)(com_classfactory.value) #pointer to IClassFactory
#and there we'll have a pointer to IUknown of the filter inside the dll
filter = ptr_icf.CreateInstance()
dec = filter.QueryInterface(qedit.IBaseFilter)
filter_graph.AddFilter(dec, "dec")
#Voila!

因此,这项工作可以在不使用任何 pythoncom 的情况下完成,这对我来说是一个很大的优势(因为之前的所有工作都是通过 comtypes 模块完成的)

关于python - 如何从 python 中的 dll 加载带有自定义接口(interface)的 COM 对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44690234/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com