DLLImport -> 如何在 C# 中处理句柄
DLLImport -> how to handle a HANDLE in C#
在我的C#代码中,我想导入一个C++DLL。我使用 dllimport,它与某些函数配合使用正常。但是在一个函数中,我得到了一个句柄,稍后我需要它来调用另一个函数。
[DllImport("SiUSBXp.dll")]
public static extern int SI_Open(UInt32 deviceNum,ref IntPtr devHandle ); // this function gets the HANDLE
[DllImport("SiUSBXp.dll")]
public static extern int SI_Write([In]IntPtr devHandle, [In, Out] byte[] inputByte, UInt32 size,ref UInt32 bytesWritten); // this function needs the HANDLE
在我的代码中,这些函数的调用方式如下:
IntPtr devHandle = new IntPtr();
UInt32 bytesWritten = new UInt32();
byte[] byteArr = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
SI_Open(0, ref devHandle);
SI_Write(devHandle, byteArr, 10, ref bytesWritten);
如果我这样做,我会得到一个"System.AccessViolationException"。我在这里和互联网上搜索,但没有找到具体的答案。如何正确使用 IntPtr,使其正常工作?此致敬意
托比
你的SI_Write函数看起来很像Windows Kernel32的WriteFile。
所以,我会这样做:
[DllImport("SiUSBXp.dll", SetLastError = true)]
static extern int SI_Open(uint dwDevice, ref IntPtr cyHandle);
[DllImport("SiUSBXp.dll", SetLastError = true)]
static extern int SI_Write(IntPtr cyHandle, byte[] lpBuffer,
uint dwBytesToWrite, out uint lpdwBytesWritten);
编辑:我在网上找到了这个文档USBXPRESS®程序员指南,它指出SI_Write原型实际上看起来比我想象的更接近WriteFile。文档指出:
SI_STATUS SI_Write (HANDLE Handle, LPVOID Buffer, DWORD NumBytesToWrite,
DWORD *NumBytesWritten, OVERLAPPED* o = NULL)
这意味着 .NET 原型应该是这样的:
[DllImport("SiUSBXp.dll")]
static extern int SI_Write(IntPtr Handle, byte[] Buffer,
uint NumBytesToWrite, out uint NumBytesWritten, IntPtr o);
o 是可选的,因此您可以传递 IntPtr.Zero。
你犯了一个经典的 C 程序员错误,你没有检查函数的返回值。 这告诉您函数是否失败。 一种可能的情况是 SI_Open() 返回了失败代码。 您忽略它并仍然使用未初始化的句柄值。 卡布姆并不罕见。
下一个可能的错误是未在 [DllImport] 语句中使用 CallingConvention 属性。 很可能需要它,Cdcl是默认值,除非使用__stdcall声明本机函数。 也是调用 kaboom 的绝佳方式。 如果您仍然遇到问题,那么您将不得不调试本机代码。
顺便说一句,您可以通过使用 out 而不是 ref 来摆脱尴尬的语法。 在这两个功能中。
[DllImport("SiUSBXp.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int SI_Open(UInt32 deviceNum, out IntPtr devHandle );
试试这个:
[DllImport("SiUSBXp.dll")]
public static extern int SI_Open(UInt32 deviceNum, ref IntPtr devHandle); // this function gets the HANDLE
[DllImport("SiUSBXp.dll")]
public static extern int SI_Write(IntPtr devHandle, ref byte[] inputByte, UInt32 size, ref UInt32 bytesWritten); // this function needs the HANDLE
编辑:
@Hans 帕桑特是对的。 这是将 byte[] 传递到 LPVOID 参数的正确方法。 ref 用于将对象强制到 LPVOID 中,但数组不需要。 当你尝试这个时会发生什么?
[DllImport("SiUSBXp.dll")]
public static extern int SI_Write(IntPtr devHandle, byte[] inputByte, UInt32 size, ref UInt32 bytesWritten); // this function needs the HANDLE
你试过穆里尔给出@Simon答案吗?他是第一个提出这一声明的人,他的回答值得接受。
不好:static extern void DoStuff(**byte[] inputByte**);
好: static extern void DoStuff(**[In, MarshalAs(UnmanagedType.LPArray)] byte[] inputByte**);
- 外壳包装器句柄/执行交互式命令管道C++ UNIX
- 如何获取边缘窗口句柄 (HWND)?
- 枚举进程模块在有效句柄上返回无效句柄
- 在 c/c++ 中打开 PhysicalDrive 的句柄并写入 MBR 的 linux 等效是什么?
- 从运行服务的应用程序代码中提取窗口句柄
- 在读取文件后重置句柄
- 是否有像地图这样的C++结构,但我得到的不是值的键,而是值的句柄?
- Microsoft ODBC 无法创建有效的句柄
- 我是否可以使用 win32 句柄以编程方式记录发送到/接收到 USB/COM 的内容
- 获取特定进程的句柄数
- C++ 创建 NdisProt 驱动程序的句柄
- 是否需要关闭来自 WinHTTP 异步的句柄?
- 句柄OK全部崩溃
- 我需要通过窗口句柄(HWND)获取文件,我该怎么办?
- 什么是 C# 等同于C++句柄
- 未知C++错误:致命错误:glibc检测到无效的stdio句柄
- MFC C++正在从WM_KEYDOWN处理程序获取在OnDraw()中编辑的CDC pDC的句柄
- C++如何获取泛型catch处理程序中抛出的异常的句柄
- 使用 cin >> 处理错误句柄
- DLLImport -> 如何在 C# 中处理句柄