James Teh schrieb:
> 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.

James,
I agree with you that this is a problem.  I'm looking into it but it seems
to take langer than expected.

> 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?

No, it was not intended to be this way.

> 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.

A possible solution would be to change the COMObject.IUnknown_QueryInterface()
and COMObject.QueryInterface() methods so that they call __prepare_comobject()
again when they find an empty _com_pointers_ dictionary.  In this way the
object can be used again even after the refcount has dropped to zero.

> Jamie
> 


-- 
Thanks,
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

Reply via email to