Re: [comtypes-users] Problem calling method

2010-02-10 Thread Thomas Heller
Am 30.01.2010 06:23, schrieb Pablo Bianucci:
 Hi!
 
 I am trying to use an ActiveX control (.OCX, from a piezo electric stage
 controller)) from a Python program. I have managed to get the control to work,
 but I am having problems calling a method.
 
 This is the method in question (from the autogenerated typelib):
 
 ===
DISPMETHOD([dispid(20)], c_int, 'GetControlMode',
( [], c_int, 'lChanID' ),
( [], POINTER(c_int), 'plMode' )),
 ===
 
 This is what I am doing trying to use the method (it should give me an 
 integer):
 
 ===
 mode = 0
 mode_ptr = cast(mode, POINTER(c_int))

What you are doing here is that you create a NULL pointer - which is probably 
not
what you want.  But see below.

 try:
 piezo1.GetControlMode(APTPiezoLib.CHAN1_ID, mode_ptr)
 except Exception, e:
 print Exception:, e
 ===
 
 And I get:
 
 ===
 Exception: Cannot put comtypes._safearray.LP_c_long object at 0x012D9440 in 
 VARIANT
 ===i
 
 I have no previous experience with comtypes or ctypes (or Win32 programming, 
 for that matter ;-)), so I might be doing something stupidly wrong. I've tried
 all the permutations I could think of already, so I need expert help. 

Ok, the interface that you have is a pure dispinterface, which means that
all methods of the COM object are eventually called as IDispatch.Invoke() calls.

The Invoke() method packs all parameters into a DISPPARAM structure which
basically is an array of VARIANT instances.  This explains the error that
you get - comtypes is trying to pack the POINTER parameter that you have
created into a VARIANT.  This only works for 'automation-compatible' data types
and your pointer is not one of those.

I would guess that the 'mode_ptr' argument is an argument that must be passed
by reference (this is visual basic speak).  Do you have sample VB code that
shows how this method is used?

However, it could be that comtypes is not able to call this method...

Thomas


--
SOLARIS 10 is the OS for Data Centers - provides features such as DTrace,
Predictive Self Healing and Award Winning ZFS. Get Solaris 10 NOW
http://p.sf.net/sfu/solaris-dev2dev
___
comtypes-users mailing list
comtypes-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/comtypes-users


[comtypes-users] Using a COMObject from a client more than once

2010-02-10 Thread James Teh
Hi.

In our project, we communicate with Microsoft SAPI 4 speech synthesisers 
using COM. When we want to speak data, we must provide an object which 
can receive events. (The IConnectionPoint* interfaces are not used.)

Following is a rough, very simplified outline of the code:

class SynthDriverBufSink(COMObject):
_com_interfaces_ = [ITTSBufNotifySink]
...

class SynthDriver(object):
def __init__(self):
self._ttsCentral = ...
self._bufSink=SynthDriverBufSink()
...

def performSpeak(self, text):
...
self._ttsCentral.TextData(..., text,
self._bufSink, ITTSBufNotifySink._iid_)

_ttsCentral.TextData accepts a pointer to IUnknown (this is defined in 
its interface), as well as the iid of the ITTSBufNotifySink interface.

The issue is that self._bufSink is created at instantiation, but is used 
in many calls to performSpeak. In comtypes 0.6.1, this was fine. 
However, in 0.6.2, when the ref count of a COMObject hits 0, the 
_com_pointers_ dict gets cleared to avoid a memory leak (svn r544). This 
means that the first call to performSpeak is fine. However, after this 
call completes, the ref count on self._bufSink will drop to 0, 
_com_pointers_ will be cleared and subsequent calls will fail to get the 
appropriate pointer.

We've fixed this by never holding the underlying COMObject. In the 
constructor, we do:
self._bufSink=SynthDriverBufSink().QueryInterface(ITTSBufNotifySink)
This way, the pointer will AddRef and keep the underlying COMObject 
alive and will Release it when the pointer gets garbage collected.

Despite the solution, this raises the question: Are we supposed to never 
maintain a long-lasting reference to an underlying COMObject? That is, 
was it always intended that a COMObject should never be held directly?
In C++, one usually has the ref count start at 1, rather than 0. I 
understand this would present challenges in Python, as you don't know 
when to clean up the object. However, it'd be good to have some policy 
documentation on this scenario.

Jamie

-- 
James Teh
Email/MSN Messenger/Jabber: ja...@jantrid.net
Web site: http://www.jantrid.net/


--
SOLARIS 10 is the OS for Data Centers - provides features such as DTrace,
Predictive Self Healing and Award Winning ZFS. Get Solaris 10 NOW
http://p.sf.net/sfu/solaris-dev2dev
___
comtypes-users mailing list
comtypes-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/comtypes-users