将字符串从 C# 传递到 C++ DLL 不同 return 类型的不同文本编码

Passing String from C# to C++ DLL different Text Encoding on different return Types

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

在我的 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é-"。

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

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

为什么会这样? C# 中的 CharSet 已设置为 Ansi 以将字符串编组为正确的类型。我不知道 return 类型和我传递的字符串之间的联系在哪里。

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

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

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

首先,在 C# 端使用 string return 类型,pinvoke 编组器假定 returned 字符串是用 CoTaskMemAlloc 分配的,并将调用 CoTaskMemFree 复制后释放它。

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

部分选项:

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