I have a COM component (in C#) that has the following interface:
namespace InterOp
{
[StructLayout(LayoutKind.Sequential)]
public struct MyStruct
{
[MarshalAs(UnmanagedType.BStr)]
public string name;
[MarshalAs(UnmanagedType.BStr)]
public string surname;
public int age;
}
public interface ITest
{
void SetStringArray(string[] array);
void SetStructArray(MyStruct[] array);
}
public class Test : ITest
{
// string arrays
public void SetStringArray(string[] array)
{
for(int i = 0; i < array.Length; i++)
MessageBox.Show(array[i]); // just do something with the array values
}
// struct arrays
public void SetStructArray(MyStruct[] array)
{
for (int i = 0; i < array.Length; i++)
MessageBox.Show(array[i].name + ", " + array[i].surname + " (" + array[i].age.ToString() + ")");// just do something with the array values
}
}
}
Now I want to pass data from C++ to that COM object. I initialized the interface like this:
HRESULT hr = CoInitialize(NULL);
ITest* pTest = NULL;
hr = CoCreateInstance(__uuidof(Test), NULL, CLSCTX_INPROC_SERVER, __uuidof(ITest), (void**)&pTest);
But I can't pass a reference to my array to that method, as it requires a SAFEARRAY* array. I was able to create SAFEARRAYs with arrays with fixed size elements like double, int, char arrays, and it works fine using something like this:
SAFEARRAY* data = SafeArrayCreate(VT_R8, 1, &bound); //8-Byte-Real, 1 dimension
Of course, for my user-defined struct there is no "VT_something", so I don't know how to create a SAFEARRAY to solve this. I tried VT_DISPATCH and VT_BSTR without success.
The actual method to pass the data is this one:
bool SetStructArrayEx(MyInterOp::MyStruct* array, int arraySize, ITest* comObjectInterface)
{
bool retVal = false;
// Create the safearray environment
SAFEARRAYBOUND bound;
bound.lLbound = 0;
bound.cElements = arraySize;
// Init the safearray
SAFEARRAY* data = SafeArrayCreate(VT_DISPATCH, 1, &bound);
// access the safearray data and copy the original data to it
MyInterOp::MyStruct HUGEP* temp;
HRESULT hr = SafeArrayAccessData(data, (void HUGEP* FAR*)&temp);
if(SUCCEEDED(hr))
{
// finally copy the data
for(int i=0; i<arraySize; ++i)
*temp++ = array[i];
comObjectInterface->SetStructArray(data);
SafeArrayUnaccessData(data);
retVal = true;
}
SafeArrayDestroy(data);
return retVal;
}
...and this does not work (Exception in Kernel32.dll when calling SetStructArray
).
Any ideas where I'm wrong? Or what would work?
Thanks, Markus