.NET Framework                
            Вызов платформы
        
        
            
    Поиск…
Синтаксис
- [DllImport ("Example.dll")] static extern void SetText (строка inString);
 - [DllImport ("Example.dll")] static extern void GetText (StringBuilder outString);
 - [MarshalAs (UnmanagedType.ByValTStr, SizeConst = 32)] текст строки;
 - [MarshalAs (UnmanagedType.ByValArray, SizeConst = 128)] byte [] byteArr;
 - [StructLayout (LayoutKind.Sequential)] public struct PERSON {...}
 - [StructLayout (LayoutKind.Explicit)] public struct MarshaledUnion {[FieldOffset (0)] ...}
 
Вызов функции dll Win32
using System.Runtime.InteropServices;
class PInvokeExample
{
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern uint MessageBox(IntPtr hWnd, String text, String caption, int options);
    public static void test()
    {
        MessageBox(IntPtr.Zero, "Hello!", "Message", 0);
    }
}
  Объявить функцию как static extern stting DllImportAttribute с свойством Value установленным в .dll name. Не забудьте использовать пространство имен System.Runtime.InteropServices . Затем назовите его как обычный статический метод. 
Службы Invocation Services позаботятся о загрузке .dll и поиске нужного результата. P / Invoke в большинстве простых случаев также будет маршалировать параметры и возвращать значение в .dll и обратно. Т.е. преобразовать из .NET типов данных в Win32 и наоборот.
Использование Windows API
Используйте pinvoke.net .
 Прежде чем объявлять extern функцию Windows API в вашем коде, попробуйте найти его на pinvoke.net . Они, скорее всего, уже имеют подходящую декларацию со всеми поддерживающими типами и хорошими примерами. 
Маршевые массивы
Массивы простого типа
[DllImport("Example.dll")]
static extern void SetArray(
    [MarshalAs(UnmanagedType.LPArray, SizeConst = 128)]
    byte[] data);
 Массивы строк
[DllImport("Example.dll")]
static extern void SetStrArray(string[] textLines);
        Структуры маршалинга
Простая структура
Подпись 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);
        Маршалинские союзы
Только поля типа значения
Декларация C ++
typedef union
{
    char c;
    int i;
} CharOrInt;
 Объявление C #
[StructLayout(LayoutKind.Explicit)]
public struct CharOrInt
{
    [FieldOffset(0)]
    public byte c;
    [FieldOffset(0)]
    public int i;
}
 Смешивание значений и ссылочных полей
 Перекрытие ссылочного значения одним типом значения не допускается, поэтому вы не можете просто использовать   не будет компилироваться для FieldOffset(0) text; FieldOffset(0) i; 
typedef union
{
    char text[128];
    int i;
} TextOrInt;
 и, как правило, вам придется использовать настраиваемый маршалинг. Однако в таких случаях, как эта более простая техника, можно использовать:
[StructLayout(LayoutKind.Sequential)]
public struct TextOrInt
{
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
    public byte[] text;
    public int i { get { return BitConverter.ToInt32(text, 0); } }
}