Looking for .net Keywords? Try Ask4Keywords

.NET Framework Структуры маршалинга


пример

Простая структура

Подпись C ++:

typedef struct _PERSON
{
    int age;
    char name[32];
} PERSON, *LP_PERSON;

void GetSpouse(PERSON person, LP_PERSON spouse);

Определение C #

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct PERSON
{
    public int age;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
    public string name;
}

[DllImport("family.dll", CharSet = CharSet.Auto)]
public static extern bool GetSpouse(PERSON person, ref PERSON spouse);

Struct с неизвестными размерами массива. Передача

Подпись C ++

typedef struct
{
    int length;
    int *data;
} VECTOR;

void SetVector(VECTOR &vector);

При переходе от управляемого к неуправляемому коду это

Массив data должен быть определен как IntPtr, и память должна быть явно выделена Marshal.AllocHGlobal() (и освобождена с помощью Marshal.FreeHGlobal() послесловия):

[StructLayout(LayoutKind.Sequential)]
public struct VECTOR : IDisposable
{
    int length;
    IntPtr dataBuf;

    public int[] data
    {
        set
        {
            FreeDataBuf();
            if (value != null && value.Length > 0)
            {
                dataBuf = Marshal.AllocHGlobal(value.Length * Marshal.SizeOf(value[0]));
                Marshal.Copy(value, 0, dataBuf, value.Length);
                length = value.Length;
            }
        }
    }
    void FreeDataBuf()
    {
        if (dataBuf != IntPtr.Zero)
        {
            Marshal.FreeHGlobal(dataBuf);
            dataBuf = IntPtr.Zero;
        }
    }
    public void Dispose()
    {
        FreeDataBuf();
    }
}

[DllImport("vectors.dll")]
public static extern void SetVector([In]ref VECTOR vector);

Struct с неизвестными размерами массива. получающий

Подпись C ++:

typedef struct
{
    char *name;
} USER;

bool GetCurrentUser(USER *user);

Когда такие данные передаются из неуправляемого кода, а память выделяется неуправляемыми функциями, управляемый вызывающий IntPrt должен получать его в переменную IntPrt и преобразовывать буфер в управляемый массив. В случае строк есть удобный Marshal.PtrToStringAnsi() :

[StructLayout(LayoutKind.Sequential)]
public struct USER
{
    IntPtr nameBuffer;
    public string name { get { return Marshal.PtrToStringAnsi(nameBuffer); } }
}

[DllImport("users.dll")]
public static extern bool GetCurrentUser(out USER user);