.NET Framework
Platform aanroepen
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 zal niet compileren voor FieldOffset(0) text; FieldOffset(0) i;
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); } }
}