将std :: string从C ++ DLL返回到c#程序 - >为RtlFreeHeap指定的地址无效

时间:2009-04-28 17:42:21

标签: c# c++ string marshalling

在我的C ++ DLL中的一个函数中,我将一个std :: string返回给我的c#应用程序。它几乎看起来像这样:

std::string g_DllName = "MyDLL";

extern "C" THUNDER_API const char* __stdcall GetDLLName()
{
    return g_DllName.c_str();
}

但是当我的C#代码调用此函数时,我在输出窗口中收到此消息:

Invalid Address specified to RtlFreeHeap( 00150000, 0012D8D8 )

c#中的函数声明如下所示:

[DllImport("MyDll", EntryPoint = "GetDLLName")]
    [return: MarshalAs(UnmanagedType.LPStr)]
    public static extern string GetDLLName();

根据我在网上找到的内容,有时会在删除时使用哪个版本的新版本(调试版或发布版等)之间出现不一致的消息。但我不确定这是不是我的情况。所以我不确定究竟是什么导致了它。也许MashallAs可能与它有关?

有什么想法吗?

谢谢!

1 个答案:

答案 0 :(得分:12)

我设法找到了这个问题。这就是C#定义的完成方式。根据我的理解,将MarshallAs(UnmanagedType.LPStr)与字符串返回类型结合使用,使得它在完成后将尝试释放字符串。但是因为字符串来自C ++ DLL,并且很可能是完全不同的内存管理器,所以它失败了。即使它没有失败,我也不希望它被释放。

我找到的解决方案是将C#声明更改为此(C ++代码未更改):

[DllImport("MyDll", EntryPoint = "GetDLLName")]
public static extern IntPtr GetDLLName();

所以这使得它只返回一个指向字符串数据的指针。然后将其更改为字符串,将其传递给Marshal.PtrToStringAnsi()

return Marshal.PtrToStringAnsi(GetDLLName());

这包含在另一个清洁功能中。

我从这个页面找到了解决方案: http://discuss.fogcreek.com/dotnetquestions/default.asp?cmd=show&ixPost=1108