2017-06-22 7 views
0

おはようございます。 タスクは、dllからロードされたCOMオブジェクトで作業することです(regsvr32の使用は禁止されています)。また、そのオブジェクトは、今後必要になるDirectShowインターフェイスを公開します。PythonでDLLからカスタムインターフェイスでCOMオブジェクトをロードするには?

次に、私はthis linkの例を使用してモジュールを取得しようとしています。問題に直面しています。pythoncomはDirectShowインターフェイス(IBaseFilterなど)について知らないです。そしてfrom this post私は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: There is no interface object registered that supports this IIDです。

したがって、comtypesは、そのインターフェイスについて知っています。しかし、残念ながら、私はcomtypesまたはctypesを使用してDLLからCOMオブジェクトをロードする方法を見つけることができません。

私は数日間この問題に取り組んできました。本当に助言をいただきたいと思います。

答えて

0

最後に、いくつかのポインタ操作が必要でしたが、私はそれを行いました。

は私がcomtypes.serverからのIClassFactoryクラス輸入し、それのために(ポインタを№1)のポインタを取得しました。その後、私はIClassFactoryへのc_longポインタを取得しました。これは、ロードしたdll(ポインタ№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! 

、ジョブが

(以前のすべての作業がcomtypesモジュールを介して行われているように見て)私には大きな利点であるpythoncom、のいずれかを使用せずに行うことができます
関連する問題