NETCF, wie übergebe ich eine Struktur per Referenz an DeviceIoControl?
-
11-12-2019 - |
Frage
Ich bin neu im .NET Compact Framework.Ich muss eine DeviceIoControl-Funktion aufrufen und Strukturen als Eingabe- und Ausgabeparameter an die IOControl-Funktion übergeben.
In PInvoke/DeviceIoControl Ich habe herausgefunden, wie ich auf die Funktion selbst zugreifen kann.Aber wie kann ich einen Zeiger auf die Struktur übergeben? InBuf
Und OutBuf
Parameter?
Das DeviceIoControl ist als P/Invoke definiert:
[DllImport("coredll", EntryPoint = "DeviceIoControl", SetLastError = true)]
internal static extern int DeviceIoControlCE(
int hDevice, int dwIoControlCode,
byte[] lpInBuffer, int nInBufferSize,
byte[] lpOutBuffer, int nOutBufferSize,
ref int lpBytesReturned, IntPtr lpOverlapped);
Die betreffenden Strukturen haben dieses Layout:
struct Query
{
int a;
int b;
char x[8];
}
struct Response
{
int result;
uint32 success;
}
void DoIoControl ()
{
Query q = new Query();
Response r = new Response();
int inSize = System.Runtime.InteropServices.Marshal.SizeOf(q);
int outSize = System.Runtime.InteropServices.Marshal.SizeOf(r);
NativeMethods.DeviceIoControlCE((int)handle, (int)IOCTL_MY.CODE,
ref q, inSize, ref r, outSize, ref bytesReturned, IntPtr.Zero);
}
Bearbeiten:Wenn ich versuche, diesen Code zu kompilieren, erhalte ich die Fehlermeldung:
cannot convert from 'ref MyNamespace.Response' to 'byte[]'
Wie kann ich die Adresse der Struktur an die DeviceIoControl-Funktion übergeben, die einen Zeiger auf ein Byte anstelle einer Strukturreferenz erwartet?
Lösung
Das Problem besteht darin, dass Ihre P/Invoke-Deklaration nicht mit Ihrem Aufruf übereinstimmt.DeviceIoControl nimmt Zeiger für die Ein-/Aus-Parameter entgegen:
BOOL DeviceIoControl(
HANDLE hDevice,
DWORD dwIoControlCode,
LPVOID lpInBuffer,
DWORD nInBufferSize,
LPVOID lpOutBuffer,
DWORD nOutBufferSize,
LPDWORD lpBytesReturned,
LPOVERLAPPED lpOverlapped
);
Sie können Ihre Deklaration also vielfältig „anpassen“.Der in dem von Ihnen angegebenen Link verwendet a byte[]
wahrscheinlich aus Bequemlichkeitsgründen dort, wo sie es verwendeten.In Ihrem Fall, da Sie einfache Strukturen übergeben (d. h.keine internen Zeiger auf andere Daten), dann besteht die einfachste „Lösung“ darin, einfach Ihre P/Invoke-Deklaration zu ändern:
[DllImport("coredll", SetLastError = true)]
internal static extern int DeviceIoControl(
IntPtr hDevice,
IOCTL.MY dwIoControlCode,
ref Query lpInBuffer,
int nInBufferSize,
ref Response lpOutBuffer,
int nOutBufferSize,
ref int lpBytesReturned,
IntPtr lpOverlapped);
Und Ihr Code sollte funktionieren.Beachten Sie, dass ich auch die Typen der ersten beiden Parameter geändert habe, um Ihren aufrufenden Code ohne Umwandlungen klarer zu gestalten.
BEARBEITEN 2
Wenn Sie feststellen, dass Sie unterschiedliche Signaturen benötigen, überladen Sie einfach P/Invoke.Zum Beispiel die Smart Device Framework Code hat mindestens 11 Überladungen für DeviceIoControl.Hier sind nur einige davon, um Ihnen einen Vorgeschmack zu geben:
[DllImport("coredll.dll", EntryPoint = "DeviceIoControl", SetLastError = true)]
internal static extern int DeviceIoControl<TInput, TOutput>(
IntPtr hDevice,
uint dwIoControlCode,
ref TInput lpInBuffer,
int nInBufferSize,
ref TOutput lpOutBuffer,
int nOutBufferSize,
out int lpBytesReturned,
IntPtr lpOverlapped)
where TInput : struct
where TOutput : struct;
[DllImport("coredll.dll", EntryPoint = "DeviceIoControl", SetLastError = true)]
internal unsafe static extern int DeviceIoControl(
IntPtr hDevice,
uint dwIoControlCode,
void* lpInBuffer,
int nInBufferSize,
void* lpOutBuffer,
int nOutBufferSize,
out int lpBytesReturned,
IntPtr lpOverlapped);
[DllImport("coredll.dll", EntryPoint = "DeviceIoControl", SetLastError = true)]
internal static extern int DeviceIoControl(
IntPtr hDevice,
uint dwIoControlCode,
IntPtr lpInBuffer,
uint nInBufferSize,
IntPtr lpOutBuffer,
uint nOutBufferSize,
out int lpBytesReturned,
IntPtr lpOverlapped);
[DllImport("coredll.dll", EntryPoint = "DeviceIoControl", SetLastError = true)]
internal static extern int DeviceIoControl(
IntPtr hDevice,
uint dwIoControlCode,
byte[] lpInBuffer,
int nInBufferSize,
IntPtr lpOutBuffer,
int nOutBufferSize,
out int lpBytesReturned,
IntPtr lpOverlapped);