Pregunta

Soy nuevo en el marco compacto .NET.Necesito llamar a una función DeviceIoControl y pasar estructuras como parámetros de entrada y salida a la función IOControl.

En PInvocar/DeviceIoControl Encontré cómo acceder a la función en sí.Pero, ¿cómo puedo pasar un puntero a la estructura como? InBuf y OutBuf ¿parámetro?

DeviceIoControl se define como P/Invoke:

[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);

Las estructuras en cuestión tienen este diseño:

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);   
}

Editar:Cuando intento compilar este código me sale el error:

cannot convert from 'ref MyNamespace.Response' to 'byte[]'

¿Cómo puedo pasar la dirección de la estructura a la función DeviceIoControl que espera un puntero a byte en lugar de referencia de estructura?

¿Fue útil?

Solución

El problema es que su declaración P/Invoke no coincide con su llamada.DeviceIoControl toma punteros para los parámetros de entrada/salida:

BOOL DeviceIoControl(
  HANDLE hDevice, 
  DWORD dwIoControlCode, 
  LPVOID lpInBuffer, 
  DWORD nInBufferSize, 
  LPVOID lpOutBuffer, 
  DWORD nOutBufferSize, 
  LPDWORD lpBytesReturned, 
  LPOVERLAPPED lpOverlapped
);

Así que puedes "ajustar" tu declaración de muchas maneras.El que está en el enlace que proporcionas utiliza un byte[] probablemente por conveniencia donde lo estaban usando.En su caso, dado que está pasando estructuras simples (es decir,no hay punteros internos a otros datos), entonces la "solución" más fácil es simplemente cambiar su declaración P/Invoke:

[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);    

Y tu código debería funcionar.Tenga en cuenta que también cambié los tipos de los dos primeros parámetros para permitir que su código de llamada sea más claro sin conversiones.

EDITAR 2

Si descubre que necesita firmas diferentes, simplemente sobrecargue P/Invoke.Por ejemplo, el Marco de dispositivos inteligentes El código tiene al menos 11 sobrecargas para DeviceIoControl.Éstos son sólo algunos de ellos para darle una idea:

    [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);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top