Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/284.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在python中从dll加载带有自定义接口的COM对象?_Python_Com_Directshow - Fatal编程技术网

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

如何在python中从dll加载带有自定义接口的COM对象?,python,com,directshow,Python,Com,Directshow,大家好。 任务是使用从dll加载的COM对象(禁止使用regsvr32)。该对象还公开了我将来需要的DirectShow接口 然后,我尝试使用来自的示例获取一个模块,我遇到了一个问题:pythoncom对DirectShow接口一无所知(例如IBaseFilter)。我的印象是pythoncom不支持定制COM接口,但那是在2008年,也许现在情况已经改变了 代码是 # -*- coding: utf-8 -*- import ctypes, inspect, os, pythoncom, sy

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

然后,我尝试使用来自的示例获取一个模块,我遇到了一个问题:pythoncom对DirectShow接口一无所知(例如IBaseFilter)。我的印象是pythoncom不支持定制COM接口,但那是在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:没有注册的接口对象支持此IID
,这是可以理解的

所以,comtypes知道这一点!但不幸的是,我找不到使用comtypes甚至ctypes从dll加载COM对象的方法


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

最后,我做了一些指针操作,但我做到了

我已经从comtypes.server导入了类IClassFactory,并为它获取了一个指针(指针№1). 之后,我获得了一个c_长指针,指向我加载的dll中的IClassFactory对象(指针№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模块完成的)

您目前知道一种直接从ctypes完成的方法吗?具体来说,我正在尝试加载