【问题标题】:cannot convert 'const char*' to 'LPCWSTR {aka const wchar_t*}'无法将 'const char*' 转换为 'LPCWSTR {aka const wchar_t*}'
【发布时间】:2017-03-31 05:00:25
【问题描述】:

我在 C++ 代码中遇到了一个我无法理解的错误。剥离的代码位在这里:

RS232Handle=OpenRS232("COM1", 9600);

HANDLE OpenRS232(const char* ComName, DWORD BaudRate)
{
    ComHandle=CreateFile(ComName, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
}

我收到以下错误:

error: cannot convert 'const char*' to 'LPCWSTR {aka const wchar_t*}' for argument '1' to 'void* CreateFileW(LPCWSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE)'
     ComHandle=CreateFile(ComName, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

代码取自 VS 代码,我现在正在使用 Qt creator。

我该如何解决这个问题?谢谢!

【问题讨论】:

  • const char *const wchar_t * 不一样,不能隐式转换。

标签: c++ qt char type-conversion wchar-t


【解决方案1】:

Windows CreateFile 函数实际上是一个宏,它扩展为以下之一:

  • CreateFileA,采用const char* 类型的文件路径
  • CreateFileW,采用const wchar_t* 类型的文件路径。

(Windows API 中大多数接受字符串的函数也是如此。)

您声明了参数const char* ComName,但显然编译时定义了UNICODE,因此它调用了函数的W 版本。没有从const wchar_t*const char* 的自动转换,因此出现错误。

您的选择是:

  1. 将函数参数更改为 UTF-16 (const wchar_t*) 字符串。
  2. 保留char* 参数,但让您的函数使用MultiByteToWideChar 之类的函数将其显式转换为UTF-16 字符串。
  3. 显式调用CreateFileA 而不是CreateFile
  4. 在不使用UNICODE 的情况下编译您的程序,以便宏默认扩展为A 版本。
  5. 绑架一位著名的 Microsoft 开发人员并强迫他阅读 UTF-8 Everywhere,直到他同意让 Windows 完全支持 UTF-8 作为“ANSI”代码页,从而使各地的 Windows 开发人员从这种宽字符的东西中解放出来。

编辑:我不知道是否涉及绑架,但 Windows 10 1903 终于添加了支持for UTF-8 as an ANSI code page

【讨论】:

  • #5 不是一个独特的选项,它只是让#2、#3 和#4 在字符串包含扩展字符时工作。
  • 在 Visual C++ 中更改字符集对我有用...
【解决方案2】:

有很多方法可以解决这个问题

  1. 打开项目属性,常规/字符集。这将设置为 Unicode 或多字节字符集。如果您希望使用 char*,请将 Unicode 更改为 MBCS。如果指定了 Unicode,这会将 CreateFile 转换为 CreateFileW,如果指定了 MBCS,则会将 CreateFileA 转换为。
  2. 将所有字符串括在 _T() 中,例如 _T("COM1")。如果指定了 MBCS,则将字符串编译为 char*,如果指定了 unicode,则将字符串编译为 wchar_t
  3. 通过以 L 为前缀,例如 L"COM1",将所有字符串强制为宽字符串

请注意,在某些错误处理例程中,字符串是专门的 MBCS

【讨论】:

    【解决方案3】:

    试试这个:

    RS232Handle=OpenRS232(L"COM1", 9600);
    
    HANDLE OpenRS232(const wchar_t* ComName, DWORD BaudRate)
    {
        ComHandle=CreateFileW(ComName, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    }
    

    在 Windows 上,wchar_t 类型用于以 UTF-16 编码表示字符。这是 Windows 内核在内部使用的,因此现代版本的 Visual C++ 默认使用 Unicode 函数。如果您坚持使用 ANSI 函数(因此回到您的原始代码),请从字符串“COM1”中删除 L-前缀并将调用从 CreateFileW 更改为 CreateFileA

    大多数处理字符串的 Windows API 函数都有WA 版本;我知道的唯一例外是函数 GetProcAddress,无论您在项目中使用的是 ANSI 还是 Unicode,它总是采用 ANSI 字符串。

    【讨论】:

    • 如果您的数据类型被硬编码为wchar_t*,请使用CreateFileWCreateFile 函数宏只能与TCHARLPCTSTR 类型宏一起使用。
    • @BenVoigt 扩展了我的答案
    【解决方案4】:

    const char*const wchar_t* 是两种不同的类型,它们之间没有隐式转换。因此,您需要在将值传递给CreateFile 函数之前执行转换。看看这个答案以了解可能的转换方法:https://stackoverflow.com/a/3074785/6710751

    或者,您也可以只使用 CreateFileA 函数而不是 CreateFile,正如 Ben Voigt 所建议的那样。

    【讨论】:

    • 或者直接致电CreateFileA,它会为您完成转换。
    • 感谢您的建议,我已将此添加到答案中。
    猜你喜欢
    • 2020-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-05
    • 1970-01-01
    • 1970-01-01
    • 2017-10-14
    • 2013-08-11
    相关资源
    最近更新 更多