开发者

StringBuilder Marshalling problem in C#

I am trying to use a C++ dll开发者_Go百科 to edit my StringBuilder object in C#. My C++ code looks like this:

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

and my C# code is:

[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);
}

After PrintHead is called, i am expecting to see that the stringBuilder object's value is changed from "123456" to "testIsOkey" , but it does not change. I can't figure out where do i make a mistake.

Thanks for your help.


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

That's not correct C++ code. It merely changes the pointer that was passed to the function. This has no side effects whatsoever. Fix:

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

But never write interop code like this, the C++ function can easily destroy the garbage collected heap this way. Which is exactly what happens in your code, the StringBuilder's Capacity isn't enough. You should add an extra argument that provides the size of the passed buffer. Fix:

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

Pass the string builder's Capacity for that extra argument, like this:

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


Doesn't it have to be marked ref or with some other attribute, so that .NET knows that the marshalling should occur both ways?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜