Search code examples
cominterop

"SafeArray cannot be marshaled to this array type" error


I have a C++ COM local server and C# client. The server code:

// 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 converts the BYTE array to SAFEARRAY. It is taken from this stackoverflow question. It sets the boundary & dimension of the SAFEARRAY.

The client code:

MyStruct myStruct;
int rc = obj.Foo(out myStruct);

Where MyStruct is imported from the COM assembly. it appears as

public struct MyStruct
{
  public Array FormatData;
  int aLong;
  int aBool;
}

After running Foo appears the error "SafeArray cannot be marshaled to this array type because it has either nonzero lower bounds or more than one dimension" with additional remark "Make sure your array has the required number of dimensions".

When debugging the server code it seems Data is properly populated in FormatData: as can be seen in screen-shot below. cElements equals Length and the 18 data pieces are equal to the ones in Data.

enter image description here

Hard-coding Length = 1 did not help. Removing the PackByets call made the error disappear (other fields were passed ok). How can this be fixed?


Solution

  • The PackBytes method that you have referenced constructs a SAFEARRAY with lower bound of 1. Constructing it with a lower bound of zero may fix the problem:

    SAFEARRAYBOUND bound{ count, 0 };