1.

Solve : Managed arrays as SAFEARRAYS in native C++?

Answer»

Hey all:

I have a question I would like to POSE regarding a resulting SAFEARRAY from managed code. I have a C# class that contains a struct and a METHOD that returns an array of that struct. For example:

Code: [Select]
struct myStruct
{
[MarshalAs(UnmanagedType.R8)]
double val1;
[MarshalAs(UnmanagedType.R8)]
double val2;
[MarshalAs(UnmanagedType.R8)]
double val3;
[MarshalAs(UnmanagedType.R8)]
double val4;

[MarshalAs(UnmanagedType.BStr)]
string name;
}

myStruct[] buildStructArray(Rectangle rect);


I can follow the progression of the method when I call it from the native C++ source code. Inside there, the code is running through and building the myStruct[] accordingly. When the C# class is COM interopped, the struct array is converted to a SAFEARRAY so the C++ progression looks something like:

Code: [Select]
SAFEARRAY *pStructArray = NULL;

myClass->buildStructArray(rect, &pStructArray );

// Get the IRecordInfo object associated with the structure.
IRecordInfoPtr spIRecordInfo = NULL;
SafeArrayGetRecordInfo(pStructArray , &spIRecordInfo);

// Get the lower and upper bounds for the inner safe array data.
long lBound = 0;
long uBound = 0;
SafeArrayGetLBound(pStructArray , 1, &lBound);
SafeArrayGetUBound(pStructArray , 1, &uBound);

long dimSize = uSubBound - lSubBound + 1;
long rgIndices[1];

for(int i = 0; i < dimSize; i++)
{
rgIndices[0] = i;

myStruct* curMyStruct;

memset(&curMyStruct, 0, sizeof(curMyStruct));

SafeArrayGetElement(pStructArray , rgIndices, &curMyStruct);

// Try to read the values from the SAFEARRAY here. The values are garbled or non-existent.

spIRecordInfo -> RecordClear((PVOID)&curMyStruct);


OK. So getting the values from the SAFEARRAY is erroneous. I am trying view the name using something along the lines of:

Code: [Select]
DisplayMessage((const char *)curMyStruct->name));


...and the double values using the code:

Code: [Select]
double curVal1 = 0.0;
double curVal2 = 0.0;
double curVal3 = 0.0;
double curVal4 = 0.0;

curVal1 = curMyStruct->val1;
curVal2 = curMyStruct->val2;
curVal3 = curMyStruct->val3;
curVal4 = curMyStruct->val4;

std::stringstream val1ss;
std::stringstream val2ss;
std::stringstream val3ss;
std::stringstream val4ss;

val1ss<< curVal1 ;
val2ss<< curVal2 ;
val3ss<< curVal3 ;
val4ss<< curVal4 ;

DisplayMessage(_T(val1ss.str().c_str()));
DisplayMessage(_T(val2ss.str().c_str()));
DisplayMessage(_T(val3ss.str().c_str()));
DisplayMessage(_T(val4ss.str().c_str()));


I am confident in the DisplayMessage function because it is used successfully throughout the code quite frequently. I am going to have to figure out why the SAFEARRAY has bogus values or find another option to using arrays.

So my question: why am I getting the erroneous values when I can see the values being stored inside the managed method when being called from the C++ code?

THANKS for any input.



Discussion

No Comment Found