johnny loops schrieb: > Thomas, thanks for your help. Everything seemed to work except when I > needed to pass my com object to another com function to receive > callbacks > >> > o=myComObjClass() >> > otherDispatchedComObject.FunctionThatNeedsInterface(o, otherInputs) > > The other dispatched com object was created using win32com, and other > functions of it work fine. However, this specific function needs to > be called with a com object implementing the interface as one of the > inputs, and then its functions will be called as callbacks. The error > I get when I pass o to this function is > > ValueError: argument is not a COM object > > Do you have any suggestions? Thanks again for your help
If I understand you correctly, you have created the otherDispatchedComObject by calling some win32com functions, and you want to pass a comtypes object to a method of otherDispatchedComObject? If this is so, then it fails because win32com does not know anything about comtypes. Fortunately, pythoncom25.dll exposes a function that can be called with ctypes to do the conversion. I have attached a module containing a unittest that does this. The 'comtypes2pywin' function accepts a comtypes COM pointer or a comtypes COMObject instance and returns a win32com object - a <PyIDispatch> object, or a <PyOIUnknown> object. I think that should do what you want - please report back. This code should probably go into comtypes somewhere. Thomas
import unittest from ctypes import PyDLL, py_object, c_void_p, byref, POINTER from ctypes.wintypes import BOOL from comtypes import IUnknown from comtypes.client import CreateObject from comtypes.automation import IDispatch import pythoncom import win32com.client # We use the PyCom_PyObjectFromIUnknown function in pythoncom25.dll to # convert a comtypes COM pointer into a pythoncom COM pointer. # Fortunately this function is exported by the dll... # # This is the C prototype; we must pass 'True' as third argument: # # PyObject *PyCom_PyObjectFromIUnknown(IUnknown *punk, REFIID riid, BOOL bAddRef) _PyCom_PyObjectFromIUnknown = PyDLL(pythoncom.__file__).PyCom_PyObjectFromIUnknown _PyCom_PyObjectFromIUnknown.restype = py_object _PyCom_PyObjectFromIUnknown.argtypes = (POINTER(IUnknown), c_void_p, BOOL) def comtypes2pywin(ptr, interface=None): """Convert a comtypes pointer 'ptr' into a pythoncom PyI<interface> object. 'interface' specifies the interface we want; it must be a comtypes interface class. The interface must be implemented by the object; and the interface must be known to pythoncom. If 'interface' is specified, comtypes.IUnknown is used. """ if interface is None: interface = IUnknown return _PyCom_PyObjectFromIUnknown(ptr, byref(interface._iid_), True) ################################################################ def comtypes_get_refcount(ptr): """Helper function for testing: return the COM reference count of a comtypes COM object""" ptr.AddRef() return ptr.Release() from comtypes import COMObject class MyComObject(COMObject): """A completely trivial COM object implementing IDispatch. Calling any methods will return the error code E_NOTIMPL (except the IUnknown methods; they are implemented in the base class.""" _com_interfaces_ = [IDispatch] ################################################################ class Test(unittest.TestCase): def tearDown(self): if hasattr(self, "ie"): self.ie.Quit() del self.ie def test_mycomobject(self): o = MyComObject() p = comtypes2pywin(o, IDispatch) disp = win32com.client.Dispatch(p) self.failUnlessEqual(repr(disp), "<COMObject <unknown>>") def test_ie(self): # Convert a comtypes COM interface pointer into a win32com COM # pointer. ie = self.ie = CreateObject("InternetExplorer.Application") # The COM refcount of the created object is 1: self.failUnlessEqual(comtypes_get_refcount(ie), 1) # IE starts invisible: self.failUnlessEqual(ie.Visible, False) # Create a pythoncom PyIDispatch object from it: p = comtypes2pywin(ie, interface=IDispatch) self.failUnlessEqual(comtypes_get_refcount(ie), 2) # Make it usable... disp = win32com.client.Dispatch(p) self.failUnlessEqual(comtypes_get_refcount(ie), 2) self.failUnlessEqual(disp.Visible, False) # Cleanup and make sure that the COM refcounts are correct del p, disp self.failUnlessEqual(comtypes_get_refcount(ie), 1) if __name__ == "__main__": unittest.main()
_______________________________________________ Python-win32 mailing list Python-win32@python.org http://mail.python.org/mailman/listinfo/python-win32