C#中的StringBuilder编组问题

时间:2011-01-16 20:08:01

标签: c# c++ marshalling stringbuilder

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

extern "C" __declspec(dllexport) void __stdcall PrintHead(char* myString)
{
   myString = "testIsOkey";
}

我的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);
}

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

感谢您的帮助。

2 个答案:

答案 0 :(得分:6)

void __stdcall PrintHead(char* myString) { 
    myString = "testIsOkey"; 
}

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

void __stdcall PrintHead(char* myString) { 
    strcpy(myString, "testIsOkey"); 
}

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

void __stdcall PrintHead(char* myString, size_t bufferSize) { 
    strcpy_s(myString, bufferSize, "testIsOkey"); 
}

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

var buffer = new StringBuilder(666);
PrintHead(buffer, buffer.Capacity);
var result = buffer.ToString();

答案 1 :(得分:-1)

是否必须将其标记为ref或具有其他某些属性,以便.NET知道编组应该双向进行?