我是.NET Compact框架的新手。我需要调用DeviceIoControl函数并将结构作为输入和输出参数传递给IOControl函数。
在PInvoke/DeviceIoControl中,我找到了如何访问函数本身。但是,如何将结构指针传递为InBuf
和OutBuf
参数?
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函数,期望指向byte的指针而不是struct ref?
答案 0 :(得分:2)
问题是您的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);