【发布时间】:2015-09-16 12:39:46
【问题描述】:
我正在尝试了解 .Net 编组,现在我正在使用字符串。我写了一个应用程序,但它没有按预期工作。我在这里做错了什么?
C++
EXPORT void GetString(wchar_t **pBuff)
{
std::wcout << "Initial string was: " << *pBuff << std::endl << "Changing its value..." << std::endl;
*pBuff = L"Hello from C++";
}
C#:
const string DLLNAME = "CppLib.dll";
static void Main(string[] args)
{
var sb = new StringBuilder(256).Append("Hello from C#");
GetString(ref sb);
Console.WriteLine("String from Dll is {0}", sb);
}
[DllImport(DLLNAME, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode)]
private static extern void GetString(ref StringBuilder pBuff);
但是当我运行它时,我得到了PInvokeStackImbalance 异常。
实际输出为:
初始字符串是:Hello from C#
改变它的值...
砰——这里抛出异常
如何解决?我试图改变CallingConvention - 当然它没有帮助,因为我在这里使用StdCall。但我没有更多的想法。
在纯 C++ 中,这段代码可以正常工作:
#include <iostream>
using namespace std;
void GetString(wchar_t **pBuff)
{
std::wcout << "Initial string was: " << *pBuff << std::endl << "Changing its value..." << std::endl;
*pBuff = L"Hello from C++!";
}
int main() {
wchar_t *pBuff = L"blablablablablablabla";
GetString(&pBuff);
std::wcout << pBuff;
return 0;
}
【问题讨论】:
-
另外,您不应该 覆盖字符串文字,除非您正在寻找守护进程。
-
另外,我不是 C++ 专家。但是,如果您使用指针并更改这样的字符串(就像在纯 C++ 代码中一样),它只会替换您分配的字节数。所以你那里也有内存泄漏。
-
你需要做的是先“删除”内存。然后
allocate再次使用new。不过,我会在你的情况下使用 std::string。 -
@AlexZhukovskiy 这里我做了一个例子,使用 std::string link
-
@KevinKal .Net marshaller 不支持 std::string 所以我可以与 char/wchar_t 字符串互操作。而且我知道内存泄漏和其他问题,但这只是一个原型。我明确表示不会释放任何内存以确保它不是某些副作用的原因。