SAFEARRAY (BSTR) как параметр [out] в DCOM не может возвращать строки

Я хочу написать сервер DCOM и клиента, чтобы они могли обмениваться некоторыми данными. Обе стороны компилируются с использованием MS Visual Studio 2008, клиент подключается с использованием чистого WinAPI, proxy / stub — это отдельная dll (на случай, если что-то из этого имеет значение). Проблема в том, что я не могу вернуть массив строк (он заполнен должным образом, но клиент получает массив пустых строк).

Сервер: Объявление IDL интерфейса COM имеет этот метод:

[id(7)] HRESULT foo([in] int arg1, [out] SAFEARRAY(int)* arg2, [out] SAFEARRAY(BSTR)* arg3);

Реализация с заголовком, сгенерированным Studio:

HRESULT STDMETHODCALLTYPE CoClass::foo(int arg1, SAFEARRAY** arg2, SAFEARRAY** arg3){
SAFEARRAYBOUND bounds;
bounds.cElements = arg1;
bounds.lBound = 0;
*arg2 = SafeArrayCreate(VT_INT, 1, &bounds);
*arg3 = SafeArrayCreate(VT_BSTR, 1, &bounds);
for(LONG i=0; i<arg1; ++i){
int int_value = 42;
BSTR string_value = SysAllocString(L"Hello");
//string_value is correct here
SafeArrayPutElement(*arg2, &i, &int_value);
SafeArrayPutElement(*arg3, &i, &string_value);
//string_value isn't destroyed here (explicitly, at least)
}
return ERROR_SUCCESS;
}

Клиент: Включенный сгенерированный студией заголовок:

virtual /* [id] */ HRESULT STDMETHODCALLTYPE foo(
/* [in] */ int arg1,
/* [out] */ SAFEARRAY * *arg2,
/* [out] */ SAFEARRAY * *arg3) = 0;

Код звонящего (pInterface правильно инициализирован, остальные вызовы успешны):

SAFEARRAY *pInts = NULL, *pStrings = NULL;
HRESULT error = pInterface->foo(23, &pInts, &pStrings);
// in debugger:
// error is ERROR_SUCCESS, pInts filled properly,
// pStrings is an array of 23 NULLs

Другие детали:

  • В IDL-файле нет другого метода с идентификатором 7;
  • С помощью [out] BSTR *str работает, строка возвращается правильно;
  • pInterface получено от CoCreateInstanceEx вызов;
  • В системе нет более старой версии сервера;
  • Код должен запускаться в Windows XP без каких-либо обновлений, поэтому использование Visual Studio 2008 — это ограничение, которое трудно обойти.

У кого-нибудь есть идеи, что я делаю не так?

1

Решение

Ответ был предоставлен Ганс Пассант в разделе комментариев.

Ответ: синтаксис добавления элементов в SAFEARRAY отличается для int а также BSTR:

// SAFEARRAY **intArray, **stringArray; LONG i;
int int_value = 42;
BSTR string_value = SysAllocString(L"Hello");

SafeArrayPutElement(*intArray, &i, &int_value);
//SafeArrayPutElement(*stringArray, &i, &string_value); //WRONG!
SafeArrayPutElement(*stringArray, &i, string_value); //Right

Обратите внимание, что синтаксис для чтения одинаков:

// SAFEARRAY *intArray, *stringArray; LONG i;
int int_value;
BSTR string_value;

SafeArrayGetElement(intArray, &i, &int_value);
SafeArrayGetElement(stringArray, &i, &string_value);
3

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector