正确的交叉平台从 std::string 转换为 'const TCHAR *'

Proper way crossplatfom convert from std::string to 'const TCHAR *'

本文关键字:const TCHAR 转换 平台 std string      更新时间:2023-10-16

我正在为 c++ 的 crossplatrofm 项目工作,我有类型std::string的变量,需要将其转换为const TCHAR *- 什么是正确的方法,可能是来自某个库的函数?

UPD 1: - 正如我在函数定义中看到的那样,有拆分窗口和非 Windows 实现:

#if defined _MSC_VER || defined __MINGW32__
#define _tinydir_char_t TCHAR
#else
#define _tinydir_char_t char
#endif

- 那么从std::string发送参数的非拆分实现真的没有办法吗?

正确的交叉平台从 std::string 转换为 'const TCHAR *'

TCHAR根本不应该在跨平台程序中使用;当然,除了与Windows API调用交互时,但这些调用需要从程序的其余部分抽象出来,否则它不会是跨平台的。因此,您只需要在 Windows 特定代码中TCHAR字符串和char字符串之间进行转换。

程序的其余部分应该使用char,并且最好假设它包含UTF-8编码的字符串。如果用户输入或系统调用返回采用不同编码的字符串,则需要确定该编码是什么,并相应地进行转换。

C++标准库的字符编码转换功能相当弱,因此没有多大用处。您可以像往常一样根据编码规范实现转换,也可以使用第三方实现。

可能是来自某个库的函数?

我推荐这个。

正如我在函数定义中看到的那样,有拆分窗口和非 Windows 实现

您使用的库不为不同的平台提供统一的 API,因此无法以真正的跨平台方式使用。您可以使用统一的函数声明编写包装库,以处理需要它的平台上的字符编码转换。

或者,您可以使用另一个库,该库提供统一的 API 并以透明方式转换编码。

TCHAR是Windows类型,它以这种方式定义:

#ifdef  UNICODE                     
typedef wchar_t TCHAR, *PTCHAR;
#else
typedef char TCHAR, *PTCHAR;
#endif

UNICODE宏通常在项目设置中定义(以防在Windows上使用Visual Studio项目时(。

您可以通过以下方式从std::string(在大多数情况下是 ASCII 或 UTF8(获取const TCHAR*

std::string s("hello world");
const TCHAR* pstring = nullptr;
#ifdef UNICODE
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
std::wstring wstr = converter.from_bytes(s);
pstring = wstr.data();
#else
pstring = s.data();
#endif

结果pstring

但强烈建议不要在其他平台上使用该TCHAR。最好在 UTF8 字符串 (char*( 中使用std::string

前几天我遇到了boost.nowide。我认为它会完全按照你想要的去做。

http://cppcms.com/files/nowide/html/

正如其他人所指出的,你不应该使用TCHAR,除非在与Windows API接口的代码中(或以Windows API为模型的库(。

另一种选择是使用 atlconv.h 中定义的字符转换类/宏。 CA2T 会将 8 位字符串转换为 TCHAR 字符串。 CA2CT将转换为常量TCHAR字符串(LPCTSTR(。 假设 8 位字符串是 UTF-8,则应指定 CP_UTF8 作为转换的代码页。

如果要声明一个包含 std::string 的 TCHAR 副本的变量:

CA2T tstr(stdstr.c_str(), CP_UTF8);

如果要调用采用 LPCTSTR 的函数:

FunctionThatTakesString(CA2CT(stdsr.c_str(), CP_UTF8));

如果你想从 TCHAR 字符串构造一个 std::string:

std::string mystdstring(CT2CA(tstr, CP_UTF8));

如果你想调用一个接受LPTSTR的函数,那么也许你不应该使用这些转换类。 (但是,如果您知道要调用的函数不会修改超出其当前长度的字符串,则可以这样做。