将字符串从 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 时超出范围,因此指针变得无效。
部分选项:
- 让调用者找到字符串缓冲区并让被调用者填充它。
- 使用
CoTaskMemAlloc
分配 returned char*
,从而满足 C# 代码的预期。
- 使用 pinvoke 编组器理解的 COM
BSTR
类型。
我希望有人能解释一下到底有什么区别:
在我的 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 时超出范围,因此指针变得无效。
部分选项:
- 让调用者找到字符串缓冲区并让被调用者填充它。
- 使用
CoTaskMemAlloc
分配 returnedchar*
,从而满足 C# 代码的预期。 - 使用 pinvoke 编组器理解的 COM
BSTR
类型。