为了账号安全,请及时绑定邮箱和手机立即绑定

Unicode 字符串不适用于 P/Invoke 中的 void

Unicode 字符串不适用于 P/Invoke 中的 void

C#
繁花如伊 2023-09-16 19:58:45
这是一个非常奇怪的问题,我不知道是什么原因造成的......在 C++ DLL 中,我有一个方法,出于演示目的,该方法非常简单,只需传入两个字符指针,一个是源,一个是目标。很简单,运行该方法时发生的所有事情就是将所有字符从一个字符串复制到另一个字符串中。这是方法:extern "C" __declspec(dllexport) void GetPersonName(wchar_t* destination, wchar_t* source) {    unsigned int i = 0;    for (i = 0; i < wcslen(source); i++) {        destination[i] = source[i];    }}而且,在 C# 中,我使用DllImport. 当我调用它时,我传入 StringBuilder 作为目标,然后传入Unicode字符串作为源(如果我只传入 ASCII 字符串,则不会发生此问题)。只是为了演示我在其中添加了两个汉字(这个)。[DllImport("CPPDLLImport.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]static extern void GetPersonName(StringBuilder output, string str);... var str = new StringBuilder(); GetPersonName(str, "Hi这个");而且,它绝对没有将我期望的内容放入 StringBuilder - 它放入:“Hi this摨玗öö”。起初,我假设我在 C++/C# 代码中犯了一个错误,因此,为了调试它,我决定返回“i”(在 C++ 方法中),以便我可以检查循环走了for多远,而且,出于某种原因,当我这样做时,它突然起作用了。当我将 C++ 方法设置为返回整数(并将其放入 C# 中的变量中,如var i = GetPersonName...)时,由于某种原因,它突然将正确的字符串(这正是“源”所在)放入 StringBuilder 中。然后我进一步测试了它,让它返回一个布尔值而不是整数,最后只是拍了return true一下 - 而且,再一次,它工作得很好。那么,只要返回类型不是 NOT void,它就有效吗?为什么我会看到这种行为?而且,我怎样才能做到即使该方法设置为“void”,它也能给出正确的输出。
查看完整描述

1 回答

?
小唯快跑啊

TA贡献1863条经验 获得超2个赞

您未能在 C++ 代码中以 null 终止目标字符串。添加空终止符,您的代码将会得到改进。


size_t len = wcslen(source);    

for (size_t i = 0; i < len; i++) {

    destination[i] = source[i];

}

destination[len] = 0;

另请注意,此代码避免调用wcslen循环的每次迭代。当然,您同样可以使用标准库功能来执行 C 字符串复制,无需编写另一个实现。


您仍然需要为字符串生成器对象设置适当的容量,否则您将面临较长字符串缓冲区溢出的风险。而且看起来您可能存在 cdecl 与 stdcall 调用约定不匹配的情况。


查看完整回答
反对 回复 2023-09-16
  • 1 回答
  • 0 关注
  • 62 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信