我是.NET Compact Framework的新手。我需要调用DeviceIoControl函数,并将结构作为输入和输出参数传递给IOControl函数。

PInvoke/DeviceIoControl中,我找到了如何访问该函数本身。但是,如何将指针传递为InBufOutBuf参数呢?

DeviceIoControl定义为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);


有问题的结构具有以下布局:

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


编辑:
当我尝试编译此代码时,出现错误:

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


我如何将结构的地址传递给DeviceIoControl函数,该函数期望指向字节的指针而不是结构ref?

最佳答案

问题是您的P / Invoke声明与您的呼叫不匹配。 DeviceIoControl接受输入/输出参数的指针:

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


因此,您可以通过多种方式“调整”声明。您提供的链接中的一个使用byte[]可能是为了方便起见。在您的情况下,由于您要传递简单的结构(即,没有内部指向其他数据的指针),因此最简单的“修复”方法是仅更改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);


而且您的代码应该可以工作。注意,我还更改了前两个参数的类型,以使调用代码更清晰,而无需强制转换。

编辑2

如果发现需要不同的签名,只需使P / Invoke重载即可。例如,Smart Device Framework代码的DeviceIoControl至少具有11个重载。以下只是其中一些给您的味道:

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

关于c# - NETCF如何通过ref将结构传递给DeviceIoControl,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/10649480/

10-12 23:20