将C字符串引用传递给C#

时间:2010-05-08 10:33:55

标签: c#

c code

extern "C" __declspec(dllexport) int export(LPCTSTR inputFile, string &msg)
{
    msg = "haha"
}

c#c​​ode

[DllImport("libXmlEncDll.dll")]
public static extern int XmlDecrypt(StringBuilder inputFile, ref Stringbuilder newMsg)
}

当我尝试检索newMsg的内容时,我遇到了一个错误,说我正在尝试写入受保护的内存区域。

从c到c#检索字符串的最佳方法是什么。感谢。

2 个答案:

答案 0 :(得分:4)

使用带有C ++类作为参数的导出的DLL即使在C ++中也是危险的。与C#互操作是不可能的。您不能使用相同的内存分配器,也无法调用构造函数和析构函数。更不用说您的C ++代码无效,它实际上不会返回字符串。

请改用C字符串。看起来像这样:

extern "C" __declspec(dllexport) 
void __stdcall XmlDecrypt(const wchar_t* inputFile, wchar_t* msg, int msgLen)
{
    wcscpy_s(msg, msgLen, L"haha");
}

[DllImport("libXmlEncDll.dll", CharSet = CharSet.Auto)]
public static extern void XmlDecrypt(string inputFile, StringBuilder msg, int msgLen)
...
    StringBuilder msg = new StringBuilder(666);
    XmlDecrypt(someFile, msg, msg.Capacity);
    string decryptedText = msg.ToString();

这些代码段的一些注释:

  • __stdcall声明符选择DLL导出的标准调用约定,这样您就不必在[DllImport]属性中使用CallingConvention属性。
  • C ++代码使用wchar_t,适合存储Unicode字符串。当您从XML文件获得的文本转换为8位字符时,这可以防止数据丢失,这是一种有损转换。
  • 选择正确的msgLen参数对于保持此代码的可靠性非常重要。不要忽略它,如果C ++代码溢出“msg”缓冲区,它将破坏垃圾收集堆。
  • 如果你真的需要使用std :: string那么你需要用C ++ / CLI语言编写一个ref类包装器,这样它就可以从System.String转换为std ::字符串。

答案 1 :(得分:0)

汉斯,

它很有效,非常感谢。顺便说一下,我在C#代码中发现了一个问题。 string inputFile只传递第一个字符。我通过编组进行了修改

[DllImport("libXmlEncDll.dll")]
public static extern void test(string file, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder msg, int msgLen);

再次,谢谢。