【问题标题】:LPCWSTR ERROR C++ argument of type is incompatible with parameter of typeLPCWSTR 错误 C++ 类型参数与类型参数不兼容
【发布时间】:2020-09-01 20:33:31
【问题描述】:
#include <iostream>
#include <WS2tcpip.h>
#include "sharedmemory.h"
#pragma comment (lib, "ws2_32.lib")

using namespace std;

#define MAP_OBJECT_NAME "$pcars2$"

void main(int argc, char* argv[]) 
{
    HANDLE fileHandle = OpenFileMapping(PAGE_READONLY, FALSE, MAP_OBJECT_NAME);

我对 C++ 比较陌生,我碰巧遇到了这个障碍。当我尝试将任何 #define 放入 OpenFileMapping() 行上的参数时,我收到一条错误消息:

C++ 类型参数与类型参数不兼容

我对这个程序的最终目标是发送一条从共享内存中获取数据的 UDP 消息。

这是我使用void 而不是int 的结果吗?我不知道。

【问题讨论】:

  • LPCWSTR 代表“表示字符串的长指针(宽)字符”。
  • 值得称赞的是,至少您没有尝试使用 C 风格强制转换来摆脱错误。

标签: c++ lpcwstr


【解决方案1】:

TCHAR 定义为wchar_tchar,具体取决于您的项目设置中是否分别定义了UNICODE

OpenFileMapping() 是一个基于TCHAR 的预处理器宏。它被定义为在其第三个参数中将const TCHAR* 指针指向一个以空字符结尾的字符串。

实际上,OpenFileMapping() 会映射到 OpenFileMappingA() (ANSI) 或 OpenFileMappingW() (Unicode) 函数,具体取决于是否定义了 UNICODE

// in winbase.h
WINBASEAPI
__out
HANDLE
WINAPI
OpenFileMappingA(
    __in DWORD dwDesiredAccess,
    __in BOOL bInheritHandle,
    __in LPCSTR lpName
    );
WINBASEAPI
__out
HANDLE
WINAPI
OpenFileMappingW(
    __in DWORD dwDesiredAccess,
    __in BOOL bInheritHandle,
    __in LPCWSTR lpName
    );
#ifdef UNICODE
#define OpenFileMapping  OpenFileMappingW
#else
#define OpenFileMapping  OpenFileMappingA
#endif // !UNICODE

大多数处理字符数据的旧版 Win32 API 被分成 AW 这样的版本。近年来推出的新 API 往往仅支持 Unicode。

在您的情况下,UNICODE 已定义,因此您尝试传递一个窄字符串文字 (const char[]),其中需要一个 Unicode 字符串 (const wchar_t*)。这就是您收到类型不匹配错误的原因。

在基于TCHAR 的API 中使用字符/字符串文字时,请使用TEXT() 宏来确保文字使用TCHAR 实际映射到的正确字符类型,例如:

#include <iostream>
#include <WS2tcpip.h>
#include "sharedmemory.h"
#pragma comment (lib, "ws2_32.lib")

using namespace std;

#define MAP_OBJECT_NAME TEXT("$pcars2$") // <-- HERE

void main(int argc, char* argv[]) 
{
    HANDLE fileHandle = OpenFileMapping(PAGE_READONLY, FALSE, MAP_OBJECT_NAME);

UNICODE 被定义时,它有效地执行了以下操作:

#include <iostream>
#include <WS2tcpip.h>
#include "sharedmemory.h"
#pragma comment (lib, "ws2_32.lib")

using namespace std;

#define MAP_OBJECT_NAME L"$pcars2$"

void main(int argc, char* argv[]) 
{
    HANDLE fileHandle = OpenFileMappingW(PAGE_READONLY, FALSE, MAP_OBJECT_NAME);

UNICODE 未定义时这样做:

#include <iostream>
#include <WS2tcpip.h>
#include "sharedmemory.h"
#pragma comment (lib, "ws2_32.lib")

using namespace std;

#define MAP_OBJECT_NAME "$pcars2$"

void main(int argc, char* argv[]) 
{
    HANDLE fileHandle = OpenFileMappingA(PAGE_READONLY, FALSE, MAP_OBJECT_NAME);

但是,现代编码实践根本不应该依赖TCHAR API。它们旨在向后兼容旧版 Win9x/ME 代码,因为微软在 2000 年代初期推动用户迁移以采用 Unicode。您应该根据需要直接使用 ANSI 或 Unicode 函数。

【讨论】:

    【解决方案2】:

    将您的字符串包装在 _T() 宏中。在项目设置中选择 Unicode WinAPI 时,它将 LPCSTR 字符串转换为 LPCWSTR。

    #define MAP_OBJECT_NAME _T("$pcars2$")
    

    【讨论】:

    • OpenFileMapping() 是 Win32 API 宏,而不是 C 运行时函数。您应该将 TEXT() 宏用于打算与 Win32 API 一起使用的文字,并将 _T() 宏用于打算与 C 运行时库一起使用的文字。 TEXT()_T() 通常 可以相互更改,因为 TCHAR (Win32) 和 _TCHAR (C) 是,但我不建议编写像这样跨越库边界的代码。
    【解决方案3】:

    一个简单的解决方案是将 OpenFileMapping 更改为 OpenFileMappingA 。此版本采用您提供的窄字符串。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-01-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多