У меня есть локальный сервер C ++ COM и клиент C #. Код сервера:
// MyStruct as define in the _i.h file
typedef /* [uuid] */ DECLSPEC_UUID("...") struct MyStruct
{
SAFEARRAY * FormatData;
LONG aLong;
BOOL aBool;
} MyStruct;
// Server method being invoked
STDMETHODIMP CMyClass::Foo(MyStruct* StreamInfo, int* result)
{
long Length;
BYTE* Data;
GetData(Length, Data);
PackBytes(Length, Data, &(StreamInfo->FormatData));
}
PackBytes
преобразует массив BYTE
в SAFEARRAY
. Это взято из этого вопроса стекопотока . Он устанавливает границу и размерность SAFEARRAY
.
Код клиента:
MyStruct myStruct;
int rc = obj.Foo(out myStruct);
Где MyStruct
импортируется из сборки COM. это выглядит как
public struct MyStruct
{
public Array FormatData;
int aLong;
int aBool;
}
После запуска Foo
появляется ошибка «SafeArray нельзя маршалировать для этого типа массива, поскольку он имеет ненулевые нижние границы или более одного измерения» с дополнительным примечанием «Убедитесь, что у вашего массива есть необходимое количество измерений».
При отладке кода сервера кажется, что Data
правильно заполнен в FormatData
: как видно на скриншоте ниже. cElements
равно Length
, а 18 частей данных совпадают с теми, что указаны в Data
.

Жесткое кодирование Length = 1
не помогло. Удаление вызова PackByets
привело к исчезновению ошибки (другие поля были переданы нормально). Как это можно исправить?