我必须在C#项目(.Net Framework 4)中使用旧的C ++库。
一般来说,我已经设置并运行了所有内容,但是将字符串值传递给库会给我带来麻烦。
我在utf-8中收到包含阿拉伯字符的字符串值。 该库正在处理iso-1256编码中的阿拉伯字符。
无论我尝试什么,我总是最终只有一堆???每当我将阿拉伯语字符串传递给图书馆时。
我的方法是将utf-8编码的字符串转换为C#代码中的iso-1256,并将结果传递给C ++库。
C#中的转换如下所示:
var bytes = encUtf8.GetBytes((string)value);
String value1256 = enc1256.GetString(Encoding.Convert(encUtf8, enc1256, bytes));
然后我继续将value1256传递给库。
调用的CLI函数将接受String ^ sVal参数。 遗留代码在内部使用CString,所以我必须转换字符串,这就是我的问题。 无论我如何转换字符串,我最终都只是???。
以下是我到目前为止尝试过的转化列表,所有转化都会产生相同的输出。当我检查调试器时,原始sVal正确显示为阿拉伯字符,但下面列出的每个转换只会导致???:
pin_ptr<const wchar_t> wch = PtrToStringChars(sVal);
CString cstring6(wch);
wchar_t* A= ( wchar_t* )( Marshal::StringToHGlobalAnsi(sVal).ToPointer() );
std::string stdString = marshal_as<std::string>(sVal);
CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>> cStringT = CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>( sVal );
CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>> cStringT2 = CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<char>>>( A );
CString cString1 = CString( sVal );
CString cString2 = CString(stdString.c_str());
CString cString3 = stdString.c_str();
CString cString4 = CString( _T( stdString.c_str() ));
CString cString5 = CString( sVal );
marshal_context^ context = gcnew marshal_context();
const char* c_s = context->marshal_as<const char*>(sVal);
显然我在这里做错了什么。 请你这么好,并指出我在这里正确的方向。
答案 0 :(得分:2)
如果你有String^
个对象,那么它只有一种可能的编码:UTF-16。为了明确地传递不同的编码,它需要是一个字节数组,而不是一个字符串。
enc1256.GetString(Encoding.Convert(encUtf8, enc1256, bytes));
你接近这条线,但并不完全。您正在使用UTF-8编码的bytes
并将它们转换为1256编码的字节数组(好),然后将其转换回UTF-16 String^
(错误)。 (如果您查看value1256
和原始的value
,它们可能完全相同。)之后,当您将所有转换转换为各种字符串时,它们就是&#39 ;所有人都在进行UTF-16的全新转换,他们可能都转换为ASCII或默认的1252代码页。
我要做的是调用Encoding::GetBytes(String^)
,然后将该字节数组传递给非托管C ++库。 (绕过UTF-8是不必要的。)一旦你切换到那个编码,试着把它想象成一个字节数组,而不是一个字符串。 (我不愿意使用任何字符串类,无论是托管还是非托管。)
您可以在C#或C ++ / CLI中调用GetBytes
,但我会使用C ++ / CLI:让C#看到的界面清洁&amp;使用C#String^
类型,而不是要求调用者知道正确的编码方式。