comtypes icon indicating copy to clipboard operation
comtypes copied to clipboard

Attributeerror thrown when mixing intout + out parameters

Open nagylzs opened this issue 8 years ago • 3 comments
trafficstars

Here is a C++ declaration for a method of a COM object:

virtual HRESULT STDMETHODCALLTYPE InitEx( 
        /* [in] */ long side,
        /* [out][in] */ IMemory __RPC_FAR *__RPC_FAR *control,
        /* [retval][out] */ long __RPC_FAR *rval
) = 0;

My problem is with the second parameter. It is an IMemory object (interface) passed by reference. This method can be called from C++ the following way:

CComPtr<IMemory> mem;
long ret,side;
HRESULT hr;

side = 1;
hr = m_Obj->InitEx(side,&mem,&ret);

You see, the mem object was not initialized. It does not need to be, because the method actually outputs a value there. But it was declared as an [out][in] parameter, and apparently I'm not able to call it from comtypes:

mem = prg.InitEx(1)
  File "C:\Python36-32\lib\site-packages\comtypes\__init__.py", line 659, in call_with_inout
    return rescode.__ctypes_from_outparam__()
AttributeError: 'tuple' object has no attribute '__ctypes_from_outparam__'

This question might be related to issue #87 , but that was already fixed.

I could actually fix this problem by changing this line of code:

https://github.com/enthought/comtypes/blob/master/comtypes/init.py#L659

into this:

        if len(outargs) == 1 and not (isinstance(rescode,tuple)):  # rescode is not iterable
            return rescode.__ctypes_from_outparam__()

And then:

mem, retcode = prg.InitEx(1)

But I believe this might not be the correct way to do this. I'm not an expert in this field, so I did not post a pull request yet. An example use case and the solution is provided here, anyway.

Can somebody please confirm that this is a bug, and this is the correct way to fix it?

Thanks.

nagylzs avatar Aug 30 '17 12:08 nagylzs

Have the same problem and fixed for now with the above suggestion. Would be nice to confirm it does not affect anything else.

ravikumars avatar Dec 15 '17 16:12 ravikumars

Think about this: if rescode is a tuple, then this line:

return rescode.__ctypes_from_outparam__()

will certainly fail, because tuples do not have a __ctypes_from_outparam__ method. My opinion is that this change cannot affect any program code that was working before. I wanted to send a PR, but first I wanted at least one more person to confirm that this is good.

nagylzs avatar Dec 18 '17 09:12 nagylzs

I could actually fix this problem by changing this line of code:

https://github.com/enthought/comtypes/blob/master/comtypes/init.py#L659

into this:

        if len(outargs) == 1 and not (isinstance(rescode,tuple)):  # rescode is not iterable
            return rescode.__ctypes_from_outparam_

The URL no longer points to the mentioned codebase. Rewriting it with a permalink, it would probably be here.

https://github.com/enthought/comtypes/blob/d70eb4aabff0941db1b97d1af0b8d61037c200b3/comtypes/init.py#L659-L660

An old bug regarding the in out parameter was resolved in #473, but I'm unclear how it affects this yet.

junkmd avatar Jan 11 '24 12:01 junkmd