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
[email protected]
http://mail.python.org/mailman/listinfo/python-win32