.NET Framework
Invocación de plataforma
Buscar..
Sintaxis
- [DllImport ("Example.dll")] static extern void SetText (string inString);
- [DllImport ("Example.dll")] static extern void GetText (StringBuilder outString);
- Texto de cadena [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)] ...}
Llamando a una función 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);
}
}
Declare una función como static extern
stting DllImportAttribute
con su propiedad Value
establecida en .dll nombre. No olvide utilizar el System.Runtime.InteropServices
nombres System.Runtime.InteropServices
. Entonces llámalo como un método estático regular.
Los Servicios de Invocación de Plataforma se encargarán de cargar el archivo .dll y encontrar la función deseada. El P / Invoke en la mayoría de los casos simples también calculará los parámetros y devolverá el valor ay desde .dll (es decir, convertir de tipos de datos .NET a Win32 y viceversa).
Usando la API de Windows
Utilice pinvoke.net .
Antes de declarar una función API extern
Windows en su código, considere buscarla en pinvoke.net . Lo más probable es que ya tengan una declaración adecuada con todos los tipos de soporte y buenos ejemplos.
Arreglando matrices
Arreglos de tipo simple.
[DllImport("Example.dll")]
static extern void SetArray(
[MarshalAs(UnmanagedType.LPArray, SizeConst = 128)]
byte[] data);
Matrices de cuerda
[DllImport("Example.dll")]
static extern void SetStrArray(string[] textLines);
Estructuras de cálculo
Estructura simple
Firma C ++:
typedef struct _PERSON
{
int age;
char name[32];
} PERSON, *LP_PERSON;
void GetSpouse(PERSON person, LP_PERSON spouse);
Definición de 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 con campos de matriz de tamaño desconocido. Pasando en
Firma C ++
typedef struct
{
int length;
int *data;
} VECTOR;
void SetVector(VECTOR &vector);
Cuando se pasa de código administrado a no administrado, este
La matriz de data
debe definirse como IntPtr y la memoria debe asignarse explícitamente con Marshal.AllocHGlobal()
(y liberarse con las Marshal.FreeHGlobal()
palabras 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 con campos de matriz de tamaño desconocido. Recepción
Firma C ++:
typedef struct
{
char *name;
} USER;
bool GetCurrentUser(USER *user);
Cuando dichos datos pasan de código no administrado y la memoria es asignada por las funciones no administradas, el llamante administrado debe recibirla en una variable IntPrt
y convertir el búfer en una matriz administrada. En el caso de cadenas, hay un método Marshal.PtrToStringAnsi()
conveniente:
[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);
Uniendo las uniones
Solo campos de valor
Declaración de C ++
typedef union
{
char c;
int i;
} CharOrInt;
Declaración de C #
[StructLayout(LayoutKind.Explicit)]
public struct CharOrInt
{
[FieldOffset(0)]
public byte c;
[FieldOffset(0)]
public int i;
}
Mezcla de tipo valor y campos de referencia.
La superposición de un valor de referencia con un tipo de valor uno no está permitida, por lo que no puede simplemente usar el no compilará para FieldOffset(0) text; FieldOffset(0) i;
typedef union
{
char text[128];
int i;
} TextOrInt;
y en general, tendría que emplear el cálculo de personalización personalizado. Sin embargo, en casos particulares como esta se pueden usar técnicas más simples:
[StructLayout(LayoutKind.Sequential)]
public struct TextOrInt
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
public byte[] text;
public int i { get { return BitConverter.ToInt32(text, 0); } }
}