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?

War es hilfreich?

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);
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top