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

djc*_*uch 9 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();
}
Run Code Online (Sandbox Code Playgroud)

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

Invalid Address specified to RtlFreeHeap( 00150000, 0012D8D8 )
Run Code Online (Sandbox Code Playgroud)

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

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

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

有任何想法吗?

谢谢!

djc*_*uch 12

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

我发现的解决方案是将C#声明更改为此(C++代码保持不变):

[DllImport("MyDll", EntryPoint = "GetDLLName")]
public static extern IntPtr GetDLLName();
Run Code Online (Sandbox Code Playgroud)

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

return Marshal.PtrToStringAnsi(GetDLLName());
Run Code Online (Sandbox Code Playgroud)

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

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