Assing a COM Interface to a Python object for callbacks

M

Mikko Ohtamaa

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)
 
A

Alan Kennedy

Mikko said:
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'm not sure how Mark Hammond's Windows extensions handle this
situation, if at all.

But I do know that Thomas Heller's "ctypes" has a COM framework which
addresses the problem. Only thing is, I don't know how robust the
current support is, given that, in Thomas own words: "Warning: work in
progress".

http://starship.python.net/crew/theller/ctypes/sum_sample.html

HTH,
 
J

John J. Lee

Alan Kennedy said:
Mikko Ohtamaa wrote: [...]
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.
[...]

See Mark Hammond's examples in the win32com/tests directory (IIRC)
that win32all installs in your Python directory. I can't remember
which example demonstrates this, but I'm pretty sure one does.
There's also been some discussion on c.l.py on this.


John
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,898
Latest member
BlairH7607

Latest Threads

Top