DISPID_VALUE and varargs weird behaviour

三世轮回 提交于 2019-12-11 17:56:36

问题


I am getting really strange behaviour mixing DISPID_VALUE and varargs in IDL/C++/VBA.

I have the following definitions in my IDL file

[
    uuid(78fc63e0-fdb5-11e1-a21f-0800200c9a66),
    dual
]
interface IPyObj : IDispatch
{
    // ...

    [propget, id(DISPID_VALUE)]
    HRESULT Item(
        [in] VARIANT* Key,
        [out, retval] VARIANT* Result
    );

    // ...
};

// ...

[entry("PyTuple"), helpstring("Builds a Python tuple object"), vararg]
HRESULT __stdcall PyTuple(
    [in] SAFEARRAY(VARIANT)* Elements,
    [out, retval] VARIANT* Result
);

The IPyObj::get_Item function stores an IDispatch pointer with var type VT_DISPATCH, as is confirmed by inspection in the immediate window in VBA:

?VarType(myPyObj(1))
 9 
?VarType(myPyObj.Item(1))
 9 
?VarType(myPyObj(1)) = vbObject
True

When I call the PyTuple function as follows

PyTuple(myPyObj.Item(1))

inside the function I find a VT_DISPATCH as expected, but when I call it like this:

PyTuple(myPyObj(1))

in the debugger I find that the SAFEARRAY contains a VT_I4!

What's going on?

I have noted that this behavior only seems to occur for vararg function, not for functions with a VARIANT* argument.


In response to ben's comment, this is the function called by PyTuple which reads the SAFEARRAY. Placing a breakpoint at the line indicated below, I can see that pData[k] contains a VT_I4. I repeat, the 'bug' only happens with this particular combination of using the default property and a vararg function.

PyObject* SafeArrayToTuple(SAFEARRAY* pSA)
{
    if(pSA->cDims != 1)
        throw Exception() << "Array is not one-dimensional while converting to Python tuple.";

    int len = (int) pSA->rgsabound->cElements;
    PyNewRef ret(PyTuple_New(len));
    VARIANT* pData;
    {
        AutoSafeArrayAccessData ad(pSA, (void**) &pData);

        for(int k=0; k<len; k++)
            // breakpoint here
            PyTuple_SET_ITEM(ret.ptr, k, VariantToPy(&pData[k]));
    }

    return ret.detach();
}

Note that using SafeArrayGetElement instead of SafeArrayAccessData doesn't change anything.

来源:https://stackoverflow.com/questions/23264098/dispid-value-and-varargs-weird-behaviour

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!