c# - 将字符串从 C# 传递到 C++ DLL 不同返回类型上的不同文本编码

标签 c# c++ marshalling dllimport dllexport

我希望有人能解释一下到底有什么区别:

在我的 C# 程序中,我想将一个字符串传递给 C++ 方法。 我的 C# 代码如下所示:

    [DllImport("Test.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
    public static extern String DoIt(String filename);

我的 C++ DLL 的内部如下所示:

__declspec(dllexport) CString DoIt(char* szFilename)
{
....
}

如果我传递字符串(例如:C:\temp\my.txt),它会变成格式错误 =>"Ôœ&°8é-"。

现在是我无法完全理解的令人困惑的部分。如果我将返回类型从 CString 更改为 char*,一切都很好。

__declspec( dllexport ) char* DoIt(char* filename)

为什么会这样? C# 中的 CharSet 已设置为 Ansi 以将字符串编码为正确的类型。我无法弄清楚返回类型和我传递的字符串之间的联系在哪里。

如果您需要更多信息,请告诉我。

最佳答案

您的代码的两个版本都是错误的。您当然不能将 CString 作为互操作类型传递。您使用简单类型进行互操作,而不是 C++ 类。

使用 char* 时的错误更微妙。在那种情况下,有两个问题。

首先,在 C# 端使用 string 返回类型,pinvoke marshaller 假定返回的字符串是用 CoTaskMemAlloc 分配的,并将调用 CoTaskMemFree 在它被复制后释放它。

其次,虽然我们看不到它,但您的 C++ 代码几乎肯定会返回指向 C++ 函数中局部变量所拥有的缓冲区的指针。显然,当函数返回时,这个局部变量超出了范围,因此指针变得无效。

一些选项:

  1. 让调用者找到字符串缓冲区并让被调用者填充它。
  2. 使用 CoTaskMemAlloc 分配返回的 char* 以满足 C# 代码的预期。
  3. 使用 pinvoke 编码器理解的 COM BSTR 类型。

关于c# - 将字符串从 C# 传递到 C++ DLL 不同返回类型上的不同文本编码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52090742/

相关文章:

C# - 获取打开的任务列表

c++ - 长 C++ 模板类型的 doxygen 换行符

c++ - 需要 C++ boost::optional 的帮助

c++ - 即使有时间延迟,cout 也不打印

c# - 如何使用 showdialog (.NET Compact Framework) 使表单居中

c# - MonoDevelop 建议将 if 语句转换为位操作

c# - 无法将字符串从托管 c# 传递到非托管 c

c# - MarshalAsAttribute 字符串数组

go - 为什么在解码后我得到不同的字节数但在编码后得到相同的结果?

c# - 如何在 Visual Studio 中使用空格自动对齐相似的代码行