2

有许多关于如何使用 BSTR* 参数调用 IDispatch::Invoke 的示例。我有这个与许多其他“SomeType *”参数一起使用,但无论我尝试什么,我都会得到类型不匹配的 HRESULT、E_OUTOFMEMORY 或访问冲突。在我看来,我在记忆方面做错了,但我正在遵循我发现的不同示例......作为旁注,最终的“[out] UINT puArgErr”参数永远不会填充导致参数索引问题。但是,我知道这是 BSTR 类型的第三个参数(我已经成功调用了另一个方法,它采用了前面的两个参数。)

VARIANTARG* v = new VARIANTARG[3];
//...Init my first 2 args
//Code omitted for initializing args 1 and 2 and wrapping everything up to call IDispatch->Invoke

//... Variation 1
VariantInit(v[2]);
BSTR val = SysAllocString(L"");
v[2].vt = VT_BSTR | BT_BYREF;
v[2].pbstrVal = &val;
//When I wrap everything up in the call to IDispatch::Invoke 
//this yields a HRESULT of Type Mismatch

*

//...Variation 2
VariantInit(v[2]);
BSTR val = SysAllocString(L"");
v[2].vt = VT_BSTR | BT_BYREF;
v[2].bstrVal = val;
//When I wrap everything up in the call to IDispatch::Invoke 
//this yields a HRESULT of E_OUTOFMEMORY

*

//...Variation 3
VariantInit(v[2]);
BSTR val = SysAllocString(L"RandomStringLargerThanTheMethodWillPlaceInTheOutParam");
v[2].vt = VT_BSTR | BT_BYREF;
v[2].bstrVal = val;
//When I wrap everything up in the call to IDispatch::Invoke 
//this yields an access violation

*

//...Variation 4
VariantInit(v[2]);
BSTR val = 0;
v[2].vt = VT_BSTR | BT_BYREF;
v[2].bstrVal = val;
//When I wrap everything up in the call to IDispatch::Invoke 
//this yields and HRESULT of 0x800706f4 A null reference pointer 
//was passed to the stub. 

我不明白为什么当我关注 BTR* 参数的其他示例时会发生这种情况……此外,我还有许多其他成功调用 IDispatch::Invoke 的方法,但是这个 BTR* 让我停了下来。

绝望,请帮助!

添加:

IDL 为:[id(0x00000171)] short GetCategory(short nIndx, short* nCat, BSTR* bszName);

4

1 回答 1

3

你们都在正确的轨道上。@HansPassant 评论将我指向“额头拍打”“尤里卡”时刻,他猜测它会因不同的参数而爆炸。第一个和第二个参数是不同的类型。反向传递 ::Invoke 它们实际上是第二个和第三个参数。所以它实际上是在类型不匹配的情况下炸毁了我的“第一个”参数。

在我最初的概念验证版本中,我手动传递参数,并且我有目的地按照 IDispatch::Invoke 的要求以相反的顺序正确传递参数。在将其转换为更通用的方法循环遍历从调用者传递的参数数组的过程中,我在调用 IDispatch::Invoke 之后将它们返回给调用应用程序时反转了参数顺序,但是,我忘记了反转他们在调用 Invoke 之前的路上。

神圣的“你知道什么”错误对于没有大量经验的人来说是如此深奥!

一旦我确定了参数的顺序,所有的行为都完全符合预期。我的问题中的“变体 1”当然是处理 BSTR* 参数的正确方法。为清楚起见,这是为 IDispatch::Invoke 调用的 BSTR* 参数初始化变体参数的正确方法(在我的情况下,这里没有显示其他 2 个参数)

VARIANTARG* v = new VARIANTARG[3];
//...Init my first 2 args IN REVERSE (not shown here)

//Init my third arg which is the BSTR* parameter
VariantInit(v[0]);
BSTR val = SysAllocString(L"");
v[0].vt = VT_BSTR | VT_BYREF;
v[0].pbstrVal = &val;
于 2014-07-10T18:03:26.767 回答