У меня есть простая структура данных C # со строкой, int и вектором целых:
class MyManagedClass
{
public string m_Str;
int m_Int;
int[] m_IntArray;
}
Эквивалент в C ++:
struct myUnmanagedStruct
{
char* m_Str;
UINT m_Int;
UINT* m_IntArray;
}
У меня неуправляемыйфункция, которая создает массив структур myUnmanagedStruct.Каков наилучший способ написать управляемую оболочку, которая правильно упорядочивает данные так, чтобы то, что создается на неуправляемой стороне, правильно передавалось обратно на управляемую сторону?(т.е. я хочу сделать массив объектов MyManagedClass из массива MyUnmanagedStructs)
Примечание:
a) Строка создается в неуправляемой структуре
b) Вектор целых чисел создается внеуправляемая структура
Моя лучшая попытка на данный момент:
На управляемой стороне:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack=1)]
public class MyManagedClass
{
public MyManagedClass()
{
m_IntArray = new int[4];
}
public String m_Str;
public int m_Int;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public int[] m_IntArray;
}
[StructLayout(LayoutKind.Sequential)]
public struct UnsafeLCEArray
{
public int m_Int;
public IntPtr m_CharBuf;
public IntPtr m_IntBuf;
}
public unsafe class LibWrap
{
// Declares managed prototypes for the unmanaged function.
[DllImport("mydll.dll", EntryPoint = "GetUnmanagedStructs")]
public static extern voidGetUnmanagedStructs(out int size, out IntPtr outArray);
}
На неуправляемой стороне:
typedef struct _MyUnmanagedStruct
{
char* m_Str;
UINT m_Int;
UINT* m_IntArray;
} MyUnmanagedStruct;
typedef struct _UNSAFELCEARRAY
{
char* strBuf;
UINT intBuf;
UINT* intArrayBuf;
} UNSAFELCEARRAY;
extern "C" __declspec(dllexport) void GetUnmanagedStructs( int* pSize, UNSAFELCEARRAY** ppStruct )
{
const int cArraySize = 5;
*pSize = cArraySize;
int numBytes = cArraySize * sizeof( MyUnmanagedStruct);
*ppStruct = (UNSAFELCEARRAY*)CoTaskMemAlloc(numBytes);
UNSAFELCEARRAY* pCurStruct = *ppStruct;
char* typenamebuffer;
char* numBuffer;
int var = 999;
for( int i = 0; i < cArraySize; i++, pCurStruct++ )
{
pCurStruct->intBuf = i+1;
typenamebuffer = (char*)CoTaskMemAlloc( 8 );
memcpy_s(typenamebuffer, 8, "bufABCD", 8);
pCurStruct->strBuf = typenamebuffer;
numBuffer = (char*)CoTaskMemAlloc( 16 );
++var;
memcpy_s(numBuffer, 4, &var, 4);
++var;
memcpy_s(numBuffer+4, 4, &var, 4);
++var;
memcpy_s(numBuffer+8, 4, &var, 4);
++var;
memcpy_s(numBuffer+12, 4, &var, 4);
pCurStruct->intArrayBuf = (UINT*)numBuffer;
}
}
Все работает, если я удаляю вектор целых из управляемых и неуправляемых объектов, но с кодом выше массив целых по возвращаемому неинициализируется.Я использую функцию ниже для генерации MyManagedClasses из MyUnmanagedStructs
int size;
IntPtr outArray;
LibWrap.GetUnmanagedStructs(out size, out outArray);
manArray = new MyManagedClass[size];
IntPtr current = outArray;
for (int i = 0; i < size; i++)
{
manArray[i] = new MyManagedClass();
Marshal.PtrToStructure(current, manArray[i]);
Marshal.DestroyStructure(current, typeof(sb_LCE));
int numBytes = Marshal.SizeOf(manArray[i]);
current = (IntPtr)((long)current + numBytes);
}
Marshal.FreeCoTaskMem(outArray);
Простите за длинное объяснение и тот факт, что неуправляемая стойка заполняется фиктивными значениями.Это только для иллюстрации.