简体   繁体   中英

StringBuilder Marshalling problem in C#

I am trying to use a C++ dll 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();

它不是必须标记为ref还是带有其他一些属性,以便.NET知道编组应该双向发生?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM