Am 13.01.2010 21:23, schrieb Allen Saunders:
>>
>> Calling COM methods is straightforward just like with other Python objects.
>> They can be called with positional and named arguments.
>>
>> Arguments marked [out] or [out, retval] in the IDL are returned from a
>> sucessful method call, in a tuple if there is more than one. If no [out]
>>  or [out, retval] arguments are present, the HRESULT returned by the
>> method call is returned. When [out] or [out, retval] arguments are
>> returned from a sucessful call, the HRESULT value is lost.
>>
>> If the COM method call fails, a COMError exception is raised, containing
>> the HRESULT value.
>>
> 
> Is it true that there is no way to get a successful HRESULT from a call that
> has [out] variables? An example is a function that can timeout, it may
> return either S_OK (0) or S_FALSE (1), an the difference between the two is
> important!
> 
> Is there anyway for me to retrieve that 'lost' HRESULT?

Yes, there is indeed a way, but it is a little bit complicated.

For the following discussion lets assume a com interface with a method
like this (IDL code):

interface IInterface : IUnknown {
   ...

   HRESULT DoSomething([in] int value, [out] int *result);
   ...
}


comtypes will create a class 'IInterface' with a method named 'DoSomething'.
This method has the signature 'result = DoSomething(value)', and returns the 
[out]
parameter but not the HRESULT value (except when it fails).

Another private method that is created is named '__com_DoSomething' and has the
signature 'hresult = __com_DoSomething(value, presult)'.  It takes two 
arguments:
An integer and a POINTER(c_int) instance; and it will return the hresult value.

So, you can either call this method directly - but you must take the name 
mangling
into account that Python does:

result = c_int()
hr = obj._IInterface__com_DoSomething(value, byref(result))
print hr
print result.value

Or you implement the DoSomething method yourself by adding this to the generated
code for the IInterface class (somewhere in comtypes\gen\<xxx>.py):

class IInterface(IUnknown):
    ...

    def DoSomething(self, value):
        result = c_int()
        hr = self.__com_DoSomething(value, byref(result))
        return hr, result.value

In this case name mangling is not needed (because the private method is called
from inside the class); and comtypes will not override your method 
implementation.

This technique is used in some interface implementations in comtypes itself to
provide a more python interface to some methods when the automatic wrapping
doesn't work so good.  Quite some examples are in comtypes\typeinfo.py,
for the ITypeLib and ITypeInfo interfaces.

-- 
Thanks,
Thomas


------------------------------------------------------------------------------
Throughout its 18-year history, RSA Conference consistently attracts the
world's best and brightest in the field, creating opportunities for Conference
attendees to learn about information security's most important issues through
interactions with peers, luminaries and emerging and established companies.
http://p.sf.net/sfu/rsaconf-dev2dev
_______________________________________________
comtypes-users mailing list
comtypes-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/comtypes-users

Reply via email to