Zoeken…


Syntaxis

  • [DllImport ("Example.dll")] statische externe void SetText (string inString);
  • [DllImport ("Example.dll")] statische externe ongeldige GetText (StringBuilder outString);
  • [MarshalAs (UnmanagedType.ByValTStr, SizeConst = 32)] string-tekst;
  • [MarshalAs (UnmanagedType.ByValArray, SizeConst = 128)] byte [] byteArr;
  • [StructLayout (LayoutKind.Sequential)] openbare struct PERSON {...}
  • [StructLayout (LayoutKind.Explicit)] openbare struct MarshaledUnion {[FieldOffset (0)] ...}

Een Win32 dll-functie aanroepen

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);
    }
}

Declareer een functie als static extern DllImportAttribute met de eigenschap Value ingesteld op .dll name. Vergeet niet om de naamruimte System.Runtime.InteropServices te gebruiken. Noem het dan als een reguliere statische methode.

De Platform Invocation Services zorgen voor het laden van de .dll en het vinden van de gewenste finction. De P / Invoke zal in de meeste eenvoudige gevallen ook parameters rangschikken en waarde retourneren van en naar de .dll (dat wil zeggen converteren van .NET datatypes naar Win32 ones en vice versa).

Windows API gebruiken

Gebruik pinvoke.net .

Overweeg voordat u een extern Windows API-functie in uw code declareert , ernaar te zoeken op pinvoke.net . Ze hebben waarschijnlijk al een geschikte verklaring met alle ondersteunende typen en goede voorbeelden.

Opstellen van arrays

Arrays van eenvoudig type

[DllImport("Example.dll")]
static extern void SetArray(
    [MarshalAs(UnmanagedType.LPArray, SizeConst = 128)]
    byte[] data);

Arrays van string

[DllImport("Example.dll")]
static extern void SetStrArray(string[] textLines);

Marshall structs

Eenvoudige struct

C ++ handtekening:

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

void GetSpouse(PERSON person, LP_PERSON spouse);

C # definitie

[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);

Structuur met matrixvelden van onbekende grootte. Passeren in

C ++ handtekening

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

void SetVector(VECTOR &vector);

Wanneer dit van beheerde naar onbeheerde code wordt doorgegeven, is dit

De data moet worden gedefinieerd als IntPtr en geheugen moet expliciet worden toegewezen met Marshal.AllocHGlobal() (en vrijgegeven met Marshal.FreeHGlobal() afterwords):

[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);

Structuur met matrixvelden van onbekende grootte. Het ontvangen

C ++ handtekening:

typedef struct
{
    char *name;
} USER;

bool GetCurrentUser(USER *user);

Wanneer dergelijke gegevens worden doorgegeven uit onbeheerde code en geheugen wordt toegewezen door de onbeheerde functies, moet de beheerde beller deze ontvangen in een variabele IntPrt en de buffer converteren naar een beheerde array. In het geval van strings is er een handige Marshal.PtrToStringAnsi() methode:

[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);

Marshall-vakbonden

Alleen waardetypevelden

C ++ verklaring

typedef union
{
    char c;
    int i;
} CharOrInt;

C # verklaring

[StructLayout(LayoutKind.Explicit)]
public struct CharOrInt
{
    [FieldOffset(0)]
    public byte c;
    [FieldOffset(0)]
    public int i;
}

Mixing type-type en referentievelden

Het overlappen van een referentiewaarde met een waardetype één is niet toegestaan, dus u kunt niet eenvoudig de FieldOffset(0) text; FieldOffset(0) i; zal niet compileren voor

typedef union
{
    char text[128];
    int i;
} TextOrInt;

en in het algemeen zou je aangepaste marshaling moeten gebruiken. In bijzondere gevallen zoals deze eenvoudiger technieken kunnen echter worden gebruikt:

[StructLayout(LayoutKind.Sequential)]
public struct TextOrInt
{
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
    public byte[] text;
    public int i { get { return BitConverter.ToInt32(text, 0); } }
}


Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow