我在C ++中有一个函数并在DLL中导出。 功能是
LONG LOGIN(LPDEVINFO 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#中调用它:
DEVINFO info = new DEVINFO();
Int id = LOGIN(info)
当我运行此代码时,出现以下错误:
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
引起的。但我不知道如何以正确的方式定义它。
提前致谢!
答案 0 :(得分:3)
使用fixed
关键字声明包含固定大小缓冲区的结构:
public unsafe struct DevInfo
{
public fixed byte sSerialNumber[20];
}
有关详细信息,请参阅Fixed Size Buffers。
此外,要通过指针传递结构(对应于本机端的LPDEVINFO
),请按如下方式声明函数:
[DllImport ('MyDll.dll')]
public static extern Int32 LOGIN(ref DevInfo info);
并称之为:
DevInfo info = new DevInfo();
int id = LOGIN(ref info)
答案 1 :(得分:3)
我会在这里使用UmanagedType.ByValArray
:
class DEVINFO {
[MarshalAs(UnmanagedType.ByValArray, SizeConst=20)]
public byte[] sSerialNumber;
}
否则一切看起来都不错。特别是使用class
而不是struct
来完成此操作非常好。
答案 2 :(得分:0)
该函数期望指向结构的指针,而不是实际结构。
使用Marshal.StructureToPtr()函数将您的结构转换为IntPtr。
C#中的示例:
[DllImport("MyDll.dll")]
public static extern Int32 LOGIN(IntPtr info);
...
DEVINFO info = new DEVINFO();
IntPtr infoPtr = Marshal.AllocHGlobal(Marshal.SizeOf(info));
Marshal.StructureToPtr(info, infoPtr, false);
LOGIN(infoPtr);
如果这是一个OUT参数,那么你需要在调用函数后从中读取它,因为它被被调用者修改了,然后你使用Marshal.PtrToStructure将它读回一个托管结构,如下所示: / p>
DEVINFO info = (DEVINFO)Marshal.PtrToStructure(infoPtr, typeof(DEVINFO));