Assing a COM Interface to a Python object for callbacks

Mikko Ohtamaa moo at sneakmail.zzn.com
Wed Jul 2 03:35:37 EDT 2003


Hi,

I am quite new to Python, PythonCom and COM generally. As a former
Java programmer, I have found Python's flexible ability to access
native Win32, especially COM, very comfortable. However, there is
quite little on-line documentation and examples available about
PythonCOM. The only good sources I have found were the sample chapter
from Mark Hammond's book and some decades old PowerPoint show.

I have a following problem:

I am trying to do XML Schema validation using MSXML SAX parser through
PythonCOM API.

MSXML offers two different interfaces for SAX: One for VB and one for
C++. C++ one is named ISAXXMLReader and VB one is named
IVBSAXXMLReader. I haven't found what is the basic difference between
these interfaces though I have carefully read MSXML SDK documentation.
I assume IVBSAXXMLReader might have some IDispatch functionality which
is requirement for PythonCom(?).

The problem is that SAX Parser requires COM interface for callback.
You must assign a COM interface as a handler to the parser. When the
parsing begins, the handler calls this interface.

saxReader.errorHandler = myErrorHandler <-- COM Interface

I do not know how to turn Python class into COM interface on the fly.

I have managed to open the C++ version ISAXXMLReader of the interface.
I have NOT succeed to do this for VB versioon IVBSAXXMLReader, because
I do not know how it happens. I assume you have to use
CoCreateInstance, but it returns "Class not registered", see the
sample below.

After opening ISAXXMLReader I have not been able to pass COM error
handler for it. I have reasons not to go through full process
registering my own error handler as a COM server into Windows registry
and create it using win32com.client.Dispatch("Python.MyErrorHandler").
Is there a way to create COM server on the fly and get the COM handle
for it? I have been trying to read win32.client and win32.server
Python sources and even PythonCOM C sources, but unfortunately my
skillz are not 1337 enough to see the big picture.

How to assign a COM Interface for a Python object? It goes somehow
through policies and wrapping, right? Unfortunately every approach I
have tried end to an error saying my wrapper IPyDispatch cannot be
used as ISAXErrorHandler.

Mikko Ohtamaa
Student of Industrial Engineering & Management
Oulu, Finland

Sample code:

class MySaxErrorHandler:

    # Some random stuff in stucked into this class
    # hoping it would help policies & wrapping
    _reg_progid_ = "Art2ComponentValidator.SaxErrorHandler"
    _reg_clsid_ = "{a60511c4-ccf5-479e-98a3-dc8dc545b7d0}"
    _reg_clsctx_ = "INPROC_SERVER"
    _com_interfaces = [ "{a60511c4-ccf5-479e-98a3-dc8dc545b7d0}" ]
    _query_interface_ = "{a60511c4-ccf5-479e-98a3-dc8dc545b7d0}"
    _public_methods_ = [ "error", "fatalError", "ignorableWarning" ]

    # A piece of VB sample:
    #Private Sub IVBSAXErrorHandler_error(ByVal oLocator As
SXML2.IVBSAXLocator,

strErrorMessage As String, ByVal nErrorCode As Long)
    #   WriteErrorToResults "Error", strErrorMessage, _
    #         nErrorCode, oLocator.lineNumber, oLocator.columnNumber
    #End Sub

    def error(oLocator, strErrorMessage, nErrorCode):
        print strErrorMessage

    def fatalError(oLocator, strErrorMessage, nErrorCode):
       print strErrorMessage

    def ignorableWarning(oLocator, strErrorMessage, nErrorCode):
        print strErrorMessage

def saxtest():

    # SAXXmlReader MIDL: a4f96ed0-f829-476e-81c0-cdc7bd2a0802
    # sax error handler: a60511c4-ccf5-479e-98a3-dc8dc545b7d0
    # ivbsaxerrorhandler: d963d3fe-173c-4862-9095-b92f66995f52
    # ivbsaxxmlreader: 8c033caa-6cd6-4f73-b728-4531af74945f
 
    # test path switcher
    useISAX = 0

    if useISAX:
        # Use c++ version ISAXXMLReader
        saxReader = win32com.client.Dispatch("Msxml2.SAXXMLReader.4.0")
        errorHandler = MySaxErrorHandler()

        # ISAXErrorHandler: a60511c4-ccf5-479e-98a3-dc8dc545b7d0

        iid = pywintypes.IID("{a60511c4-ccf5-479e-98a3-dc8dc545b7d0}")

        # What I should do instead of this?
        saxReader.errorHandler =
win32com.server.util.wrap(errorHandler, iid)

        # Following error:
        #  File "C:\Python22\Lib\site-packages\win32com\server\util.py",
line 28, in wrap
        #    ob = ob.QueryInterface(iid)       # Ask the PyIDispatch
if it supports it?
        # pywintypes.com_error: (-2147467262, 'No such interface
supported', None, None)

    else:
        # Use VB version, IVBSAXXMLreader
        clsid = pywintypes.IID("{8c033caa-6cd6-4f73-b728-4531af74945f}")
        iid = clsid
        create_as = win32com.client.pythoncom.CLSCTX_INPROC_SERVER
        iface = win32com.client.pythoncom.CoCreateInstance(clsid,
None, create_as, iid)
        # pywintypes.com_error: (-2147221164, 'Class not registered',
None, None)




More information about the Python-list mailing list