C# 中的 StringBuilder 编组问题

发布于 2024-10-12 00:27:33 字数 703 浏览 7 评论 0原文

我正在尝试使用 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" ,但它没有改变。我不知道我在哪里犯了错误。

感谢您的帮助。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

挽清梦 2024-10-19 00:27:33
void __stdcall PrintHead(char* myString) { 
    myString = "testIsOkey"; 
}

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

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

但永远不要像这样编写互操作代码,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();
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();
压抑⊿情绪 2024-10-19 00:27:33

是否必须将其标记为 ref 或使用其他一些属性,以便 .NET 知道编组应该以两种方式进行?

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文