У меня есть компонент COM (в C #), который имеет следующий интерфейс:
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
}
}
}
Теперь я хочу передать данные из C ++ в этот COM-объект.
Я инициализировал интерфейс следующим образом:
HRESULT hr = CoInitialize(NULL);
ITest* pTest = NULL;
hr = CoCreateInstance(__uuidof(Test), NULL, CLSCTX_INPROC_SERVER, __uuidof(ITest), (void**)&pTest);
Но я не могу передать ссылку на мой массив этому методу, так как для этого требуется массив SAFEARRAY *. Мне удалось создать SAFEARRAY с массивами с элементами фиксированного размера, такими как double, int, char, и это прекрасно работает, используя что-то вроде этого:
SAFEARRAY* data = SafeArrayCreate(VT_R8, 1, &bound); //8-Byte-Real, 1 dimension
Конечно, для моей пользовательской структуры нет "VT_something", поэтому я не знаю, как создать SAFEARRAY для решения этой проблемы. Я попытался VT_DISPATCH и VT_BSTR без успеха.
Фактический способ передачи данных:
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;
}
... и это не работает (исключение в Kernel32.dll при вызове SetStructArray
).
Есть идеи, где я не прав? Или что будет работать?
Спасибо,
Markus