问题
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