PInvoke:将文本从C ++恢复到C#时出错

时间:2011-09-05 04:41:24

标签: c# c++ pinvoke

我正在使用Pinvoke实现Native(C ++)代码和Managed(C#)代码之间的互操作性。我想要实现的是从本机代码中获取一些文本作为重新引用的代码,即我的C#代码调用我的C ++函数,它将一些文本返回给C#。以下是我的代码。

C ++代码:

static std::wstring WSTR_TEMP;
wchar_t* cppReturnSomeText()
 {
     UnicodeString usText ("Some Text Here");
     WSTR_TEMP = ECUtilsICU::UniCodeStringToWString(usText);
     return  (wchar_t *)(WSTR_TEMP.c_str());
 }

C#代码:

[DllImport(MY_DLL_NAME]
[return: MarshalAs(UnmanagedType.LPWStr)]
private static extern string cppReturnSomeText();
public static string GetSomeText()
{
string s = cppReturnSomeText();
return s;
}

每件事都按预期工作正常。现在我只需将操作系统从WinXP(32位)更改为Win7(64位)。当我在发生错误后运行此代码时:

“尝试读取或写入受保护的内存。这通常表示其他内存已损坏。”

1 个答案:

答案 0 :(得分:2)

我想问题是你用C ++运行时的分配器分配内存,但C#marshaller试图解除分配它。那不行。您需要使用相同的分配器分配和取消分配。

我知道解决问题的最佳方法是使用BSTR编组。这使用了很快在本机模块和托管模块之间共享的COM分配器。

#include <comutil.h>
BSTR cppReturnSomeText()
{
    UnicodeString usText("Some Text Here");
    std::wstring result = ECUtilsICU::UniCodeStringToWString(usText);
    return ::SysAllocString(result.c_str());
}

在C#端,您可以这样做:

[DllImport(MY_DLL_NAME, CallingConvention=CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.BStr)]
private static extern string cppReturnSomeText();

这样做的另一个好处是您的代码现在是线程安全的,因为您不再需要全局变量。