C# 在C中作为参数传递包含数组的结构指针# 我有C++的功能,在DLL中导出。 功能是 LONG LOGIN(LPDEVINFO info);
C# 在C中作为参数传递包含数组的结构指针# 我有C++的功能,在DLL中导出。 功能是 LONG LOGIN(LPDEVINFO info);,c#,pinvoke,dllimport,C#,Pinvoke,Dllimport,LPDEVINFO的结构是: struct{ BYTE sSerialNumber[20]; } *LPDEVINFO; 为了传递LPDEVINFO参数,我在托管代码中定义了一个类: class DEVINFO{ Byte[] sSerialNumber = new Byte[20]; } 然后像这样p/Invoke: [DllImport ('MyDll.dll')] public static extern Int32 LOGIN(DEVINFO info);
LPDEVINFO
的结构是:
struct{
BYTE sSerialNumber[20];
} *LPDEVINFO;
为了传递LPDEVINFO
参数,我在托管代码中定义了一个类:
class DEVINFO{
Byte[] sSerialNumber = new Byte[20];
}
然后像这样p/Invoke:
[DllImport ('MyDll.dll')]
public static extern Int32 LOGIN(DEVINFO info);
然后用C#来称呼它:
运行此代码时,出现以下错误:
An unhandled exception of type 'System.AccessViolationException' occurred in WindowsFormsApplication1.exe
Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
我认为问题是由数组sSerialNumber
引起的。但我不知道如何用正确的方式来定义它
提前谢谢 使用
fixed
关键字声明包含固定大小缓冲区的结构:
public unsafe struct DevInfo
{
public fixed byte sSerialNumber[20];
}
有关详细信息,请参阅
另外,要通过指针传递结构(对应于本机端的LPDEVINFO
),请按如下方式声明函数:
[DllImport ('MyDll.dll')]
public static extern Int32 LOGIN(ref DevInfo info);
并称之为:
DevInfo info = new DevInfo();
int id = LOGIN(ref info)
使用
fixed
关键字声明包含固定大小缓冲区的结构:
public unsafe struct DevInfo
{
public fixed byte sSerialNumber[20];
}
有关详细信息,请参阅
另外,要通过指针传递结构(对应于本机端的LPDEVINFO
),请按如下方式声明函数:
[DllImport ('MyDll.dll')]
public static extern Int32 LOGIN(ref DevInfo info);
并称之为:
DevInfo info = new DevInfo();
int id = LOGIN(ref info)
函数需要指向结构的指针,而不是实际结构的指针 使用Marshal.StructureToPtr()函数将结构转换为IntPtr C#中的示例: 如果这是一个OUT参数,即调用函数后需要从中读取,因为被调用方对其进行了修改,然后使用Marshal.PtrToStructure将其读回托管结构,如下所示:
DEVINFO info = (DEVINFO)Marshal.PtrToStructure(infoPtr, typeof(DEVINFO));
函数需要指向结构的指针,而不是实际结构的指针 使用Marshal.StructureToPtr()函数将结构转换为IntPtr C#中的示例: 如果这是一个OUT参数,即调用函数后需要从中读取,因为被调用方对其进行了修改,然后使用Marshal.PtrToStructure将其读回托管结构,如下所示:
DEVINFO info = (DEVINFO)Marshal.PtrToStructure(infoPtr, typeof(DEVINFO));
我会在这里使用
UmanagedType.ByValArray
:
class DEVINFO {
[MarshalAs(UnmanagedType.ByValArray, SizeConst=20)]
public byte[] sSerialNumber;
}
否则我觉得一切都很好。特别是,使用
类而不是结构来实现这一点非常好,我将在这里使用UmanagedType.ByValArray
:
class DEVINFO {
[MarshalAs(UnmanagedType.ByValArray, SizeConst=20)]
public byte[] sSerialNumber;
}
否则我觉得一切都很好。特别是,使用<代码>类<代码>,而不是<代码>结构> <代码> > < /p>如果“代码>长< /C>”被定义为C++中的64位整数类型,则必须将函数导出为<代码> ExtIn 64登录(DeViFielo信息);代码>或外部长登录(DEVINFO info)代码>。至于您的DEVINFO
类,我将使其成为一个结构,并将属性[MarshalAs(UnmanagedType.ByValArray,SizeConst=20)]
应用于字节数组@吉姆<代码>长< /Cord>是Windows上C和C++的32位整数。我不知道为什么会这样。@Jim这是一个非常常见的陷阱,LONG
与LONG
相同,在Windows上是32位的C。在C<代码>长< /COD>是64位。谢谢@ JimSuuBube,[ MarshalAs(unMaundType,ByValSalm,SsieCuSt= 20)]为我工作。如果<代码>长< /C> >被定义为C++中的64位整数类型,则必须将函数导出为<代码> ExtIn 64登录(DeViFielo信息);<代码>或外部长登录(DEVINFO info)代码>。至于您的DEVINFO
类,我将使其成为一个结构,并将属性[MarshalAs(UnmanagedType.ByValArray,SizeConst=20)]
应用于字节数组@吉姆<代码>长< /Cord>是Windows上C和C++的32位整数。我不知道为什么会这样。@Jim这是一个非常常见的陷阱,LONG
与LONG
相同,在Windows上是32位的C。在C#中,long
是64位。感谢@JimSchubert,[marshallas(UnmanagedType.ByValArray,SizeConst=20)]对我有用。根据问题中的代码,使用类而不是struct意味着将传递指针。这不是问题,布拉德利的答案更好。我只是习惯于在奇怪的互操作场景中使用StructureToPtr,比如指向指向结构的指针数组的指针,在这些场景中,简单的ref功能是不够的。使用class
就可以了。我一直这么做。关键是这个事实使得你的答案的全部内容无效。根据问题中的代码,使用类而不是struct意味着将传递一个指针。这不是问题,布拉德利的答案更好。我只是习惯于在奇怪的互操作场景中使用StructureToPtr,比如指向指向结构的指针数组的指针,在这些场景中,简单的ref功能是不够的。使用class
就可以了。我一直这么做。关键是这个事实使得你的答案的全部内容无效。我对这个答案的否决票和布拉德利答案的否决票感到困惑。我看不出他们俩有什么问题。如果有什么不对劲,我想纠正它。我对这个答案的否决票和布拉德利答案的否决票感到困惑。我看不出他们俩有什么问题。如果有什么问题,我想纠正它。关键字“fixed”,我得到错误CS0214:指针和固定大小的缓冲区只能在不安全的环境中使用context@englefly您可能需要在struct声明(修改了我的答案)和(可能)使用它的代码中添加unsafe
。您还需要在C#项目属性中启用不安全代码。使用关键字“fixed”,我得到错误CS0214:指针和固定大小的缓冲区只能在不安全的环境中使用context@englefly您可能需要在struct声明(修改了我的答案)和(可能)使用它的代码中添加unsafe
。您还需要在C#项目属性中启用不安全代码。