C#中的StringBuilder编组问题

0 c# c++ stringbuilder marshalling

我试图使用C++ DLL在C#中编辑我的StringBuilder对象.我的C++代码如下所示:

extern "C" __declspec(dllexport) void __stdcall PrintHead(char* myString)
{
   myString = "testIsOkey";
}
Run Code Online (Sandbox Code Playgroud)

我的C#代码是:

[DllImport("StringEdit.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = false)]

public static extern void PrintHead([MarshalAs(UnmanagedType.LPStr)] StringBuilder stringBuilder);

private void button1_Click(object sender, EventArgs e)
{
   StringBuilder stringBuilder = new StringBuilder("123456");
   PrintHead(stringBuilder);
}
Run Code Online (Sandbox Code Playgroud)

在调用PrintHead之后,我希望看到stringBuilder对象的值从"123456"更改为"testIsOkey",但它不会更改.我无法弄清楚我在哪里弄错了.

谢谢你的帮助.

Han*_*ant 6

void __stdcall PrintHead(char* myString) { 
    myString = "testIsOkey"; 
}
Run Code Online (Sandbox Code Playgroud)

这不是正确的C++代码.它只是改变传递给函数的指针.这没有任何副作用.固定:

void __stdcall PrintHead(char* myString) { 
    strcpy(myString, "testIsOkey"); 
}
Run Code Online (Sandbox Code Playgroud)

但是从不写这样的interop代码,C++函数可以很容易地以这种方式破坏垃圾收集堆.这正是你的代码中发生的事情,StringBuilder的容量还不够.您应该添加一个额外的参数,该参数提供传递的缓冲区的大小.固定:

void __stdcall PrintHead(char* myString, size_t bufferSize) { 
    strcpy_s(myString, bufferSize, "testIsOkey"); 
}
Run Code Online (Sandbox Code Playgroud)

为这个额外的参数传递字符串构建器的容量,如下所示:

var buffer = new StringBuilder(666);
PrintHead(buffer, buffer.Capacity);
var result = buffer.ToString();
Run Code Online (Sandbox Code Playgroud)

  • 对PrintHead的调用实际上应该是'PrintHead(buffer,buffer.Capacity + 1);' 考虑由封送程序添加的空字节.有关详细信息,请参阅http://msdn.microsoft.com/en-us/library/s9ts558h.aspx的底部. (3认同)