Маршалинг строит со строками и массивами из управляемого в неуправляемый код - PullRequest
1 голос
/ 21 апреля 2011

У меня есть простая структура данных 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);

Простите за длинное объяснение и тот факт, что неуправляемая стойка заполняется фиктивными значениями.Это только для иллюстрации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...