我有一个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来传递给函数,它仍然有效。然后我添加了一个字节数组供我通过,这有效。然后我试图将该字节数组转换为引用,但它失败了。所以我的猜测是我的数据不正确。
非常感谢任何帮助。
答案 0 :(得分:6)
尝试将[In]
更改为[In, Out]
。我也不确定在一个参数上同时使用ref
和[In, Out]
个关键字。 (编辑:Hans Passant在下面的评论中对两者之间的差异做了很好的解释。)
有关详细信息,请参阅this MSDN article,尤其是段落,“默认情况下,由于性能原因,按值传递的引用类型(类,数组,字符串和接口)被封送为In参数。您没有看到更改除非您将InAttribute和OutAttribute(或只是OutAttribute)应用于方法参数,否则应使用这些类型。“
答案 1 :(得分:1)
在升级到Windows 7之后,我开始定期在本机互操作中获得此异常。如果我在XP兼容模式下运行我的应用程序,代码一直在XP上运行,并且在Win 7上的问题更少。
经过一些研究和实验后,我发现我得到此异常的原因与调用返回字符串的本机函数(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());
}