C#的问题 C ++ DLLImport“试图读取或写入受保护的内存。”

我有一个C ++ DLL,其中有一个函数,我试图从C#应用程序调用。

这是C ++头文件中的代码

extern "C" _declspec(dllexport) int LabelStoringSSDsim(int devNum, UCHAR serial[40], UCHAR wwn[40], UCHAR ConfigID[5], UCHAR FrmRev[8], UCHAR DevName[40], int eCode); 

这是C ++源文件中的代码

 int LabelStoringSSDsim(int devNum, UCHAR serialLbl[40], UCHAR wwnLbl[40], UCHAR ConfigID[5], UCHAR FrmRev[8], UCHAR DevName[40], int eCode) 

{

 string strConfigID="12111"; //5 bytes string strFrmRev="1.25...."; //8 bytes string strDevName="ABC-123................................."; //40 bytes for (int i=0;i<5;i++) ConfigID[i] = strConfigID[i]; for (int i=0;i<8;i++) FrmRev[i] = strFrmRev[i]; for (int i=0;i<40;i++) DevName[i] = strDevName[i]; return eCode; 

}

这是C#相关代码

  [DllImport("LabelStoring.dll")] static extern int LabelStoringSSDsim( int devNum, byte[] strserial, byte[] strwwn, [In] ref byte[] ConfigID, [In] ref byte[] FrmRev, [In] ref byte[] DevName, int eCode); int errNum = LabelStoringSSDsim(devNum, bserial, bwwn, ref ConfigID, ref FrmRev, ref DevName, 123123); 

因此,当我到达最后一段代码时,我得到“尝试读取或写入受保护的内存。这通常表明其他内存已损坏。” 错误。

我之前没有像这样导入DLL的经验,我已经做了很多搜索,但似乎无法找到问题的解决方案。

我尝试从头开始用一个简单的函数返回一个整数,这是有效的。 然后我为我添加了一个int传递给函数,它仍然有效。 然后我添加了一个字节数组供我通过,这有效。 然后我试图将该字节数组转换为引用,但它失败了。 所以我的猜测是我正在错误地获取数据。

任何帮助是极大的赞赏。

尝试将[In]更改为[In, Out] 。 我也不确定在一个参数上同时使用ref[In, Out]关键字。 (编辑:Hans Passant在下面的评论中对两者之间的差异做了很好的解释。)

有关详细信息,请参阅此MSDN文章 ,特别是段落,“默认情况下,由于性能原因,值传递的引用类型(类,数组,字符串和接口)被封送为In参数。除非您看到这些类型,否则不会看到这些类型的更改将InAttribute和OutAttribute(或只是OutAttribute)应用于方法参数。“

在升级到Windows 7之后,我开始定期在本地互操作中获得此exception。如果我在XP兼容模式下运行我的应用程序,代码一直在XP上工作并且Win 7上的问题更少。

经过一些研究和实验后,我发现我得到此exception的原因与调用返回字符串的本机函数(WCHAR *)有关。

我不相信目前有一个解决方案,因为即使更新到.Net 3.5也没有解决问题…但是我确实找到了以下解决方法。

什么在XP上有效但在Win 7上不起作用的示例:

 [DllImport("NativeBin.dll")] public static extern String GetWCharStr(); 

在Win 7和XP上对我有用的示例:

 [DllImport("NativeBin.dll")] private static extern IntPtr GetWCharStr(); public static String GetString() { return Marshal.PtrToStringUni(GetWCharStr()); }