2016-06-30 2 views
0

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

Сервер: IDL декларации COM интерфейса имеет этот метод:

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

осуществление, с заголовком, сгенерированные студиями:

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 

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

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

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

+1

BSTR уже указатель, проход string_value вместо & string_value. –

+0

@ HansPassant ... это сработало. Спасибо. Вы хотите написать ответ, или я должен сделать это сам? – Abstraction

+0

Я уверен, что теперь вы знаете, как написать правильный ответ, пойти на это. –

ответ

2

Ответ предоставлен Hans Passant в разделе комментариев.

Ответ: Синтаксис добавления элементов 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); 
Смежные вопросы