无法将命名管道名称分配给 LPTSTR 变量
Posted
技术标签:
【中文标题】无法将命名管道名称分配给 LPTSTR 变量【英文标题】:Can't assign named pipe name to LPTSTR variable 【发布时间】:2021-06-06 21:40:22 【问题描述】:我已经习惯了win32 API的恶作剧,但这很烦人,我这次面临的问题是命名管道名称的分配,这就是我正在做的事情:
LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\mynamedpipe");
这是verbatim from MSDN webpages,令人惊讶的是,这不会编译并发出以下错误:
E0144 “const wchar_t *”类型的值不能用于初始化“LPTSTR”类型的实体
现在演员将解决分配,但我得到一个 109 错误,你猜对了,ERROR_BROKEN_PIPE
。
我应该如何解决这个问题?
【问题讨论】:
更改LPTSTR
-> LPCTSTR
- 错字?需要是指向 const
的指针以指向文字字符串。旧的 MSVC 曾经允许这样做,但后来的版本更符合 C++ 标准。
@RichardCritten 好吧,如果是,它不是我的,它来自 Microsoft,但它似乎使错误消失了,我将不得不检查损坏的管道错误是否也消失了。跨度>
你根本不需要声明lpszPipename
。直接将"\\\\.\\pipe\\mynamedpipe"
传递给CreateNamedPipeW
。 ERROR_BROKEN_PIPE
- 绝对是另一个问题和问题
【参考方案1】:
问题在于,尽管有相反的说法,WinAPI 文档中给出的示例(大部分)是用 C 编写的,而不是 C++。此外,在 C++(自 C++11 起)中不再允许使用字符串文字来初始化非const
字符指针。
所以,替换:
LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\mynamedpipe");
与:
TCHAR lpszPipename[] = TEXT("\\\\.\\pipe\\mynamedpipe");
(不过,这是否会修复您的 ERROR_BROKEN_PIPE
是另一回事!)
【讨论】:
请注意,您链接的示例中的代码编译为 C(尽管有一堆关于printf
格式不匹配的警告),即使在最新的 Visual Studio 中也是如此。
当然不需要这个替换。可能的LPCTSTR lpszPipename = TEXT("\\\\.\\pipe\\mynamedpipe");
替换。但这通常也不需要。只需CreateNamedPipeW(TEXT("\\\\.\\pipe\\mynamedpipe"),..)
这里甚至不需要任何const_cast
。 api 获取指向常量字符串的指针。原始代码中的 2 个错误 - 使用变量 lpszPipename (它需要什么?)并错误声明它 - 只需将 LPTSTR
更改为 LPCTSTR
【参考方案2】:
LPTSTR
是非常量版本。您正在尝试获取指向字符串文字的非常量指针。
这曾经是有效的 C++(它仍然是有效的 C,因此是示例),但它非常危险,因此在 C++11 中它们是非法的。你要么想要:
wchar_t const* lpszPipename = L"\\\\.\\pipe\\mynamedpipe";
或
wchar_t pipename[] = L"\\\\.\\pipe\\mynamedpipe";
【讨论】:
我真的希望 microsoft 文档没有那么多的小鬼,但这将是我的第二选择 ;) 我用的是const_cast<TCHAR*>
@anastaciu 不要使用讨厌的演员表,只需使用数组语法。如果代码试图改变字符串文字,没有强制转换可以拯救你。
@anastaciu 请记住,数组将具有与字符串文字不同的生命周期。
@anastaciu 很高兴我们能提供帮助!【参考方案3】:
CreateNamedPipe
使用指向 constant 字符串(LPCSTR 或 LPCWSTR)的指针代替管道名称。所以直接做
CreateNamedPipe(TEXT("\\\\.\\pipe\\mynamedpipe"), ..)
我不认为有任何理由
LPCTSTR lpszPipename = TEXT("\\\\.\\pipe\\mynamedpipe");
CreateNamedPipe(lpszPipename , ..)
但是,如果出于某种原因使用lpszPipename
- 它必须声明为指向常量字符串的指针。 LPCTSTR lpszPipename
而不是 LPTSTR lpszPipename
可能的下一个解决方案 - 在全局范围内声明
static const WCHAR gPipename[] = L"\\\\.\\pipe\\mynamedpipe";
并使用它,在二进制级别 CreateNamedPipeW(L"\\\\.\\pipe\\mynamedpipe"), ..)
和 CreateNamedPipeW(gPipename, ..)
生成相同的代码
【讨论】:
好吧,我最终使用了 LPCSTR,因为我不喜欢函数参数中的字符串文字,感谢您的帮助,I solved the problem,它与既定的无关。所有答案都是正确的,所以我接受了当时得票更多的答案,再次感谢您的帮助。 @anastaciu - 我不喜欢函数参数中的字符串字面量 为什么?临时任务有什么意义?事实上你做x = y, z = x
什么时候可以z = y
也许你是对的,这是一种习惯,我所有的字符串文字我通常都保存为常量存储在某个接口中,所以我猜这就是它的来源。
在这种情况下特别有用,因为此管道将由客户端和服务器使用,因此它可以避免字符串中的拼写错误。
@anastaciu 我将在全局范围内声明 static const WCHAR gPipename[] = L"\\\\.\\pipe\\mynamedpipe";
并使用它以上是关于无法将命名管道名称分配给 LPTSTR 变量的主要内容,如果未能解决你的问题,请参考以下文章