.NET Framework
Plattform aufrufen
Suche…
Syntax
- [DllImport ("Example.dll")] statisch extern void SetText (Zeichenfolge inString);
- [DllImport ("Example.dll")] statisch extern void GetText (StringBuilder outString);
- [MarshalAs (UnmanagedType.ByValTStr, SizeConst = 32)] Zeichenfolgentext;
- [MarshalAs (UnmanagedType.ByValArray, SizeConst = 128)] Byte [] ByteArr;
- [StructLayout (LayoutKind.Sequential)] public struct PERSON {...}
- [StructLayout (LayoutKind.Explicit)] öffentliche Struktur MarshaledUnion {[FieldOffset (0)] ...}
Aufrufen einer Win32-DLL-Funktion
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);
}
}
Deklarieren Sie eine Funktion als static extern
indem Sie DllImportAttribute
mit der Eigenschaft Value
auf .dll name setzen. Vergessen Sie nicht, den Namespace System.Runtime.InteropServices
zu verwenden. Dann rufen Sie es als normale statische Methode auf.
Die Platform Invocation Services kümmern sich darum, die DLL zu laden und die gewünschte Funktion zu finden. In den meisten einfachen Fällen wird das P / Invoke auch Parameter marshallieren und Werte von und zur DLL zurückgeben (dh Konvertierung von .NET-Datentypen in Win32-Datentypen und umgekehrt).
Windows-API verwenden
Verwenden Sie pinvoke.net .
Bevor Sie eine extern
Windows-API-Funktion in Ihrem Code deklarieren, sollten Sie sie auf pinvoke.net suchen . Sie haben höchstwahrscheinlich bereits eine passende Erklärung mit allen unterstützenden Typen und guten Beispielen.
Marshalling-Arrays
Arrays einfacher Art
[DllImport("Example.dll")]
static extern void SetArray(
[MarshalAs(UnmanagedType.LPArray, SizeConst = 128)]
byte[] data);
Arrays von Zeichenfolgen
[DllImport("Example.dll")]
static extern void SetStrArray(string[] textLines);
Marshaling-Strukturen
Einfache Struktur
C ++ - Signatur:
typedef struct _PERSON
{
int age;
char name[32];
} PERSON, *LP_PERSON;
void GetSpouse(PERSON person, LP_PERSON spouse);
C # -Definition
[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);
Struktur mit Arrayfeldern unbekannter Größe. Übergeben
C ++ - Signatur
typedef struct
{
int length;
int *data;
} VECTOR;
void SetVector(VECTOR &vector);
Wenn dieser Code von verwaltetem an nicht verwalteten Code übergeben wird
Das data
ist als IntPtr definiert und Speicher sollte explizit zugewiesen Marshal.AllocHGlobal()
(und befreit Marshal.FreeHGlobal()
anschliessend):
[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);
Struktur mit Arrayfeldern unbekannter Größe. Empfang
C ++ - Signatur:
typedef struct
{
char *name;
} USER;
bool GetCurrentUser(USER *user);
Wenn solche Daten aus nicht verwaltetem Code übergeben werden und der Speicher von den nicht verwalteten Funktionen zugewiesen wird, sollte der verwaltete Aufrufer sie in eine IntPrt
Variable empfangen und den Puffer in ein verwaltetes Array konvertieren. Im Fall von Strings gibt es eine praktische 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);
Gewerkschaften marschieren
Nur Felder mit Werttyp
C ++ - Deklaration
typedef union
{
char c;
int i;
} CharOrInt;
C # -Deklaration
[StructLayout(LayoutKind.Explicit)]
public struct CharOrInt
{
[FieldOffset(0)]
public byte c;
[FieldOffset(0)]
public int i;
}
Wertetyp und Referenzfelder mischen
Die Überlappung eines Referenzwerts mit dem Werttyp Eins ist nicht zulässig. Sie können also nicht einfach den wird nicht für kompilieren FieldOffset(0) text; FieldOffset(0) i;
typedef union
{
char text[128];
int i;
} TextOrInt;
Im Allgemeinen müssten Sie ein benutzerdefiniertes Marshalling verwenden. In besonderen Fällen wie dieser können jedoch einfachere Techniken verwendet werden:
[StructLayout(LayoutKind.Sequential)]
public struct TextOrInt
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
public byte[] text;
public int i { get { return BitConverter.ToInt32(text, 0); } }
}