Есть много примеров того, как вызвать IDispatch :: Invoke с параметром BSTR *. У меня это работает со многими другими параметрами «SomeType *», но независимо от того, что я пытаюсь, я получаю HRESULT типа Несоответствие типов, E_OUTOFMEMORY или нарушение прав доступа. Мне кажется, что я делаю что-то не так с памятью, но я следую различным примерам, которые я нашел … Как примечание, финал «[out] UINT Аргумент «puArgErr» никогда не заполняется индексом аргумента, вызывающим проблему. Однако я знаю, что это третий аргумент типа BSTR (Я успешно вызвал другой метод, который принимает 2 предыдущих аргумента.)
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 это:
[Идентификатор (0x00000171)]
короткий GetCategory (
короткий nIndx,
короткий * nCat,
BSTR * bszName);
Вы были на правильном пути. Комментарий @HansPassant указал мне на момент «eureka» «удара по лбу», когда он предположил, что он взорвался по другому параметру. 1-й и 2-й параметры имеют другой тип. Передано в обратном порядке для :: Invoke, они на самом деле 2-й и 3-й параметры. Так что на самом деле это был взрыв моего «первого» параметра с несоответствием типов.
В моей первоначальной версии для проверки концепции я вручную передавал параметры и целенаправленно передавал параметры в обратном порядке, как того требует IDispatch :: Invoke. В процессе преобразования этого в более общий подход, проходящий через массив параметров, передаваемых от вызывающей стороны, я менял порядок параметров ПОСЛЕ вызова IDispatch :: Invoke, когда я возвращал их вызывающему приложению, однако я забыл обратить вспять они на пути до звонка в Invoke.
Святые «ты знаешь, что» ошибки настолько эзотеричны для кого-то, у кого нет такого опыта!
После того, как я установил порядок параметров, все стало в точности так, как ожидалось. «Вариант 1» из моего вопроса, конечно, был правильным способом обработки параметра BSTR *. Для ясности, вот правильный способ инициализации варианта параметра для параметра BSTR *, вызываемого IDispatch :: Invoke (в моем случае есть 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 | BT_BYREF;
v[0].pbstrVal = &val;