无法将命名管道名称分配给 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" 传递给CreateNamedPipeWERROR_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 变量的主要内容,如果未能解决你的问题,请参考以下文章

无法将环境变量传递给 azure 管道 yaml 中的 powershell 脚本(非内联)

OpenCV Python,从命名管道中读取视频

将命名范围值分配给变量(Excel VBA) - 新手

Azure 管道无法生成,因为它找不到类型或命名空间名称

有没有更好的方法来命名管道`cv::mat`变量

如何等待 n 秒以打开命名管道?