C# 互操作返回 System.Access.Violation
C# interop returning System.Access.Violation
我正在尝试通过 C# Interop 使用 C 函数,但我收到一个函数的访问冲突。我尝试了很多方法,但似乎无法解决这个问题。
这里是需要改成c#代码的C代码:
typedef struct
{
char SerNo[64];
unsigned char hwVer;
HANDLE device; // Set by the API on return from SelectDevice()
} DeviceT;
此结构由以下函数使用:
error = GetDevices(DeviceT *devices, unsigned int *numDevs, unsigned int maxDevs)
C代码中还有一个函数:
error = SelectDevice(DeviceT *device)
所以我开始定义 DeviceT。我尝试了几种方法,但因为它很简单,所以决定使用它:
[StructLayout(LayoutKind.Sequential)]
public struct DeviceT
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
public char[] SerNo;
public byte hwVer;
public IntPtr device;
}
GetDevices 函数设置为:
[DllImport("file.dll", CallingConvention = CallingConvention.Cdecl)]
public unsafe static extern ErrT GetDevices([In, Out] DeviceT[] devices, uint* numDevs, uint maxDev);
SelectDevices 函数设置为:
[DllImport("file.dll", CallingConvention = CallingConvention.Cdecl)]
public unsafe static extern ErrT SelectDevice([In, Out] DeviceT devices);
代码如下:
uint numDevs = 6;
uint maxDev = 6;
uint chosenIdx = 0;
DeviceT[] devices = new DeviceT[6];
err = GetDevices(devices, &NumberOfDevices, maxDev))
此时一切正确。设备数组中包含正确的信息。
我现在继续(我只是硬编码 select 第一个设备)
chosenIdx = 0;
var chosenDevice = devices[chosenIdx];
err = SelectDevice(chosenDevice);
最后一个函数returns一个System.Access违规
我尝试了一大堆东西,但最终都得到了相同的结果。我怀疑它与 HANDLE 有关,但我不确定。
感谢您的帮助。
SelectDevice
采用 DeviceT *
,但你的 P/Invoke 签名采用 DeviceT
。也就是说,您按值传递 DeviceT
而不是传递指针。
尝试:
[DllImport("file.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern ErrT SelectDevice([In, Out] ref DeviceT devices);
err = SelectDevice(ref chosenDevice);
我正在尝试通过 C# Interop 使用 C 函数,但我收到一个函数的访问冲突。我尝试了很多方法,但似乎无法解决这个问题。
这里是需要改成c#代码的C代码:
typedef struct
{
char SerNo[64];
unsigned char hwVer;
HANDLE device; // Set by the API on return from SelectDevice()
} DeviceT;
此结构由以下函数使用:
error = GetDevices(DeviceT *devices, unsigned int *numDevs, unsigned int maxDevs)
C代码中还有一个函数:
error = SelectDevice(DeviceT *device)
所以我开始定义 DeviceT。我尝试了几种方法,但因为它很简单,所以决定使用它:
[StructLayout(LayoutKind.Sequential)]
public struct DeviceT
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
public char[] SerNo;
public byte hwVer;
public IntPtr device;
}
GetDevices 函数设置为:
[DllImport("file.dll", CallingConvention = CallingConvention.Cdecl)]
public unsafe static extern ErrT GetDevices([In, Out] DeviceT[] devices, uint* numDevs, uint maxDev);
SelectDevices 函数设置为:
[DllImport("file.dll", CallingConvention = CallingConvention.Cdecl)]
public unsafe static extern ErrT SelectDevice([In, Out] DeviceT devices);
代码如下:
uint numDevs = 6;
uint maxDev = 6;
uint chosenIdx = 0;
DeviceT[] devices = new DeviceT[6];
err = GetDevices(devices, &NumberOfDevices, maxDev))
此时一切正确。设备数组中包含正确的信息。
我现在继续(我只是硬编码 select 第一个设备)
chosenIdx = 0;
var chosenDevice = devices[chosenIdx];
err = SelectDevice(chosenDevice);
最后一个函数returns一个System.Access违规
我尝试了一大堆东西,但最终都得到了相同的结果。我怀疑它与 HANDLE 有关,但我不确定。 感谢您的帮助。
SelectDevice
采用 DeviceT *
,但你的 P/Invoke 签名采用 DeviceT
。也就是说,您按值传递 DeviceT
而不是传递指针。
尝试:
[DllImport("file.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern ErrT SelectDevice([In, Out] ref DeviceT devices);
err = SelectDevice(ref chosenDevice);