Question concerning makepy.py for COM (long, code included)

6 views
Skip to first unread message

Scott Anderson

unread,
Feb 9, 2000, 3:00:00 AM2/9/00
to pytho...@python.org
Hi all,

I have a 32-bit ActiveX OCX control that I wish to use in Python.
Please forgive any obvious ignorance on COM... I have, however, read the
QuickStarts and other related materials.

I ran the makepy.py script that comes with the win32com distribution
(the 128 release). From the file produced, it is not entirely obvious
how to instantiate and use the objects.

The code produced is included below; I changed the names because I'm not
sure of the confidentiality, and I removed code that doesn't appear
germane to the question.

TSHSWAPI is the COM object that is actually used in, say, VB. However,
_DTSHSWAPI is the one that appears to export the methods for that class.

So, the question is, how do I use the _DTSHSWAPI functionality from this
class? Also, how is the event interface implemented?

Thanks muchly in advance,

-scott

# Created by makepy.py version 0.3.1 from xxxxx.ocx
# On date: Tue Feb 08 16:14:15 2000
makepy_version = '0.3.1'

[...]

class _DTSHSWAPI(DispatchBaseClass):
CLSID = pythoncom.MakeIID('{the class ID 3}')

def AboutBox(self):
return self._ApplyTypes_(0xfffffdd8, 1, (24, 0), (), 'AboutBox', None)

def AckHost(self):
return self._ApplyTypes_(0x9, 1, (2, 0), (), 'AckHost', None)

def CloseSession(self):
return self._ApplyTypes_(0x4, 1, (2, 0), (), 'CloseSession', None)

def EnableHost(self):
return self._ApplyTypes_(0xb, 1, (2, 0), (), 'EnableHost', None)

def GetCommStatus(self, CommType=defaultNamedNotOptArg):
return self._ApplyTypes_(0x5, 1, (2, 0), ((2, 0),), 'GetCommStatus',
None, CommType)

def OpenSession(self, HostType=defaultNamedNotOptArg,
DeviceType=defaultNamedNotOptArg, PortType=defaultNamedNotOptArg):
return self._ApplyTypes_(0x2, 1, (2, 0), ((2, 0), (2, 0), (8, 0)),
'OpenSession', None, HostType, DeviceType, PortType)

def RetrieveAvailableIATAs(self, ReturnString=defaultNamedNotOptArg,
ReturnStringLength=defaultNamedNotOptArg,
HostType=defaultNamedNotOptArg, DeviceType=defaultNamedNotOptArg,
PortType=defaultNamedNotOptArg, ReturnIATACount=defaultNamedNotOptArg):
return self._ApplyTypes_(0xa, 1, (2, 0), (((26, 8), 0), (2, 0), (2,
0), (2, 0), (8, 0), ((26, 2), 0)), 'RetrieveAvailableIATAs', None,
ReturnString, ReturnStringLength, HostType, DeviceType, PortType,
ReturnIATACount)

def RetrieveIATAString(self, ReturnString=defaultNamedNotOptArg,
ReturnStringLength=defaultNamedNotOptArg):
return self._ApplyTypes_(0x7, 1, (2, 0), (((26, 8), 0), (2, 0)),
'RetrieveIATAString', None, ReturnString, ReturnStringLength)

def RetrievePrintDeviceInfo(self,
WorkstationName=defaultNamedNotOptArg,
ReturnString=defaultNamedNotOptArg,
ReturnStringLength=defaultNamedNotOptArg):
return self._ApplyTypes_(0x8, 1, (2, 0), ((8, 0), ((26, 8), 0), (2,
0)), 'RetrievePrintDeviceInfo', None, WorkstationName, ReturnString,
ReturnStringLength)

def RetrieveProtocolType(self, ReturnString=defaultNamedNotOptArg,
ReturnStringLength=defaultNamedNotOptArg):
return self._ApplyTypes_(0x6, 1, (2, 0), (((26, 8), 0), (2, 0)),
'RetrieveProtocolType', None, ReturnString, ReturnStringLength)

def Send(self, Data=defaultNamedNotOptArg,
DataLength=defaultNamedNotOptArg):
return self._ApplyTypes_(0x3, 1, (2, 0), ((8, 0), (3, 0)), 'Send',
None, Data, DataLength)

_prop_map_get_ = {
"ApplicationName": (1, 2, (8, 0), (), "ApplicationName", None),
}
_prop_map_put_ = {
"ApplicationName" : ((1, LCID, 4, 0),()),
}

class _DTSHSWAPIEvents:
CLSID = CLSID_Sink = pythoncom.MakeIID('{the class ID 2}')
_public_methods_ = [] # For COM Server support
_arg_transformer_ = arg_transformer
_dispid_to_func_ = {
1 : "OnSessionStatus",
2 : "OnHostStatus",
5 : "OnLanStatus",
4 : "OnDataAvailable",
3 : "OnMessageError",
}

def __init__(self, oobj = None):
if oobj is None:
self._olecp = None
else:
import win32com.server.util

cpc=oobj._oleobj_.QueryInterface(pythoncom.IID_IConnectionPointContainer)
cp=cpc.FindConnectionPoint(self.CLSID_Sink)
cookie=cp.Advise(win32com.server.util.wrap(self))
self._olecp,self._olecp_cookie = cp,cookie
def __del__(self):
try:
self.close()
except pythoncom.com_error:
pass
def close(self):
if self._olecp is not None:
cp,cookie,self._olecp,self._olecp_cookie =
self._olecp,self._olecp_cookie,None,None
cp.Unadvise(cookie)
def _query_interface_(self, iid):
import win32com.server.util
if iid==self.CLSID_Sink: return win32com.server.util.wrap(self)

# Handlers for the control
# If you create handlers, they should have the following prototypes:
# def OnSessionStatus(self, SubCondition=defaultNamedNotOptArg):
# def OnHostStatus(self, SubCondition=defaultNamedNotOptArg):
# def OnLanStatus(self, SubCondition=defaultNamedNotOptArg):
# def OnDataAvailable(self, SubCondition=defaultNamedNotOptArg,
Data=defaultNamedNotOptArg, DataLength=defaultNamedNotOptArg,
EraseWrite=defaultNamedNotOptArg, LineAddress=defaultNamedNotOptArg):
# def OnMessageError(self, SubCondition=defaultNamedNotOptArg):

[...]

# This CoClass is known by the name 'XXXXX.TSHSWAPICtrl.1'
class TSHSWAPI(CoClassBaseClass): # A CoClass
CLSID = pythoncom.MakeIID("{the class ID 1}")
coclass_sources = [
_DTSHSWAPIEvents,
]
default_source = _DTSHSWAPIEvents
coclass_interfaces = [
_DTSHSWAPI,
]
default_interface = _DTSHSWAPI


[...]

CLSIDToClassMap = {
'{the class ID 1}' : TSHSWAPI,
'{the class ID 2}' : _DTSHSWAPIEvents,
'{the class ID 3}' : _DTSHSWAPI,
}


Mark Hammond

unread,
Feb 9, 2000, 3:00:00 AM2/9/00
to
"Scott Anderson" <sand...@ttm.com> wrote in message
news:38A1859D...@ttm.com...

> I ran the makepy.py script that comes with the win32com distribution
> (the 128 release). From the file produced, it is not entirely
obvious
> how to instantiate and use the objects.

You dont need to do anything special - just call
"win32com.client.Dispatch(prog_id)" and it should work.

> So, the question is, how do I use the _DTSHSWAPI functionality from
this
> class? Also, how is the event interface implemented?

Events are much newer, and suffer from even worse documentation than
the rest. Only docs for events are in docstrings for
win32com.client.DispatchWithEvents() and win32com.client.getevents()

For even more details, check out my 'conferences' starship page and
look for the IPC8 tutorial...

Mark.


Scott Anderson

unread,
Feb 9, 2000, 3:00:00 AM2/9/00
to pytho...@python.org
mham...@skippinet.com.au wrote:
> > I ran the makepy.py script that comes with the win32com
distribution
> > (the 128 release). From the file produced, it is not entirely
> obvious
> > how to instantiate and use the objects.
>
> You dont need to do anything special - just call
> "win32com.client.Dispatch(prog_id)" and it should work.

That's dynamic dispatch. I was under the impression that makepy
generated a Python module suitable for doing static dispatch...

From this page
(http://www.python.org/windows/win32com/COMTutorial/img042.htm) I had
gotten the idea that I should just be able to do "o = foo.TSHSWAPI()"
(from the code I posted) and get a working object (this does not work,
hence my question).

Thanks,

-scott


Mark Hammond

unread,
Feb 10, 2000, 3:00:00 AM2/10/00
to
"Scott Anderson" <sand...@ttm.com> wrote in message
news:38A1EE08...@ttm.com...
> mham...@skippinet.com.au wrote:

> >
> > You dont need to do anything special - just call
> > "win32com.client.Dispatch(prog_id)" and it should work.
>
> That's dynamic dispatch. I was under the impression that makepy
> generated a Python module suitable for doing static dispatch...

Nope - once makepy is run, it is early-bound dispatch.
win32com.client.dynamic.Dispatch forces dispatch.

> From this page
> (http://www.python.org/windows/win32com/COMTutorial/img042.htm) I
had
> gotten the idea that I should just be able to do "o =
foo.TSHSWAPI()"
> (from the code I posted) and get a working object (this does not
work,
> hence my question).

That is a few years old now, and makepy is smarter. Check out the
"conferences" link from my starship page and look for this years
conference, then find "late and early bound" references in that...

Or-just-buy-the-book-<wink>-ly,

Mark.


Toby Dickenson

unread,
Feb 10, 2000, 3:00:00 AM2/10/00
to
Scott Anderson <sand...@ttm.com> wrote:

>mham...@skippinet.com.au wrote:
>> You dont need to do anything special - just call
>> "win32com.client.Dispatch(prog_id)" and it should work.
>
>That's dynamic dispatch. I was under the impression that makepy
>generated a Python module suitable for doing static dispatch...

win32com.client.Dispatch chooses the best form of dispatch out of all
those available. Its preferred choice it to use makepy's output, if
its available.

If you want to force dynamic dispatch, use
win32com.client.dynamic.Dispatch

If you want to force use of the makepy output, the best thing to do is
copy the module from makepy's cache directory, give it a sensible
name, possibly add it to your revision control system, and import it
directly. In your case:

import scotts_controls
o = scotts_controls.TSHSWAPI()

If you choose this latter option then you should be aware that you
will not be able to use the easier of the two Event support options
provided by win32com.client, DispatchWithEvents. You will have to use
the lower level getevents.

Toby Dickenson
tdick...@geminidataloggers.com

Scott Anderson

unread,
Feb 11, 2000, 3:00:00 AM2/11/00
to pytho...@python.org
mham...@skippinet.com.au wrote:
[...]

> Nope - once makepy is run, it is early-bound dispatch.

Gotcha. Thanks.

Next question then, since I'm getting the same error from static
dispatch as I am from dynamic: are OCX controls treated differently than
"normal" COM objects?

"ApplicationName" is a defined property of the control that I have
makepy'd, but I am unable to set it.

Here's what I'm getting:

>>> x = Dispatch('API.APICtrl.1')
>>> x
<win32com.gen_py.API ActiveX Control module._DWSHSTAPI>
>>> x.ApplicationName = 'foo'
Traceback (innermost last):
File "<stdin>", line 1, in ?
File
"C:\dev\python\win32com\gen_py\DBD89B20-C44F-11CF-8C05-0004AC77A721x0x1x0.py",
line 50, in __setattr__
pywintypes.com_error: (-2147418113, 'Unexpected failure', None, None)

Thanks,

-scott


Mark Hammond

unread,
Feb 13, 2000, 3:00:00 AM2/13/00
to
"Scott Anderson" <sand...@ttm.com> wrote in message
news:38A42C9B...@ttm.com...
> mham...@skippinet.com.au wrote:

> Next question then, since I'm getting the same error from static
> dispatch as I am from dynamic: are OCX controls treated differently
than
> "normal" COM objects?

Nope - everything is just a COM object.

> Here's what I'm getting:

...


>
"C:\dev\python\win32com\gen_py\DBD89B20-C44F-11CF-8C05-0004AC77A721x0x
1x0.py",
> line 50, in __setattr__
> pywintypes.com_error: (-2147418113, 'Unexpected failure', None,
None)

This is simply an error that has been returned from the object.
Python (or me) has no idea what has caused this. Sorry.

Mark.


Scott Anderson

unread,
Feb 14, 2000, 3:00:00 AM2/14/00
to pytho...@python.org
Interesting. I get this error on properties, methods, everything.

Perhaps the control has some internal initialization that occurs only
after it has been dropped on a VB form.

Oh well, thanks anyways.

Regards,

-scott

> > Here's what I'm getting:
> ..
> >

Reply all
Reply to author
Forward
0 new messages