首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何通过引用将结构传递给DeviceIoControl

如何通过引用将结构传递给DeviceIoControl
EN

Stack Overflow用户
提问于 2012-05-18 08:49:00
回答 1查看 1.7K关注 0票数 2

我是.NET紧凑型框架的新手。我需要调用一个DeviceIoControl函数,并将结构作为输入和输出参数传递给IOControl函数。

PInvoke/DeviceIoControl中,我发现了如何访问函数本身。但是,如何将结构作为InBufOutBuf参数传递给指针呢?

DeviceIoControl被定义为P/Invoke:

代码语言:javascript
复制
[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);

有关建筑物的布局如下:

代码语言:javascript
复制
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);   
}

编辑:当我试图编译这段代码时,我得到了错误:

代码语言:javascript
复制
cannot convert from 'ref MyNamespace.Response' to 'byte[]'

如何将结构的地址传递给DeviceIoControl函数什么是指向字节的指针而不是struct?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-05-18 13:05:46

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

代码语言:javascript
复制
BOOL DeviceIoControl(
  HANDLE hDevice, 
  DWORD dwIoControlCode, 
  LPVOID lpInBuffer, 
  DWORD nInBufferSize, 
  LPVOID lpOutBuffer, 
  DWORD nOutBufferSize, 
  LPDWORD lpBytesReturned, 
  LPOVERLAPPED lpOverlapped
);

所以你可以在很多方面“调整”你的声明。在您提供的链接中,使用byte[]可能是为了方便他们使用它的地方。在您的示例中,由于您传递的是简单的结构(即没有指向其他数据的内部指针),那么最简单的“修复”就是更改您的P/Invoke声明:

代码语言:javascript
复制
[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即可。例如,智能设备框架代码至少有11个DeviceIoControl重载。这里有一些是为了给你一些味道:

代码语言:javascript
复制
    [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);
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10649480

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档