在C#中传递包含数组作为参数的结构指针

时间:2011-12-23 17:38:44

标签: c# pinvoke dllimport

我在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引起的。但我不知道如何以正确的方式定义它。

提前致谢!

3 个答案:

答案 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));