将字符串转换为 LPCWSTR 以用于 CreateFile() 以寻址串行端口

Posted

技术标签:

【中文标题】将字符串转换为 LPCWSTR 以用于 CreateFile() 以寻址串行端口【英文标题】:Converting a string to LPCWSTR for CreateFile() to address a serial port 【发布时间】:2010-09-24 02:31:28 【问题描述】:

在使用 Windows CreateFile 函数寻址串行端口时,我似乎遇到了一些 TEXT / UNICODE 问题。有人可以帮忙指出我的错误吗?

我正在使用 VS 2008 在 VC++ 中编写一个 Win32 控制台应用程序。

我可以像这样创建一个句柄来寻址串行端口:

#include <iostream>    
#include <windows.h>
#include <string>

int main()


   HANDLE hSerial;

   hSerial = CreateFile( L"\\\\.\\COM20",
                         GENERIC_READ | GENERIC_WRITE,
                         0,
                         0,
                         OPEN_EXISTING,
                         FILE_ATTRIBUTE_NORMAL,
                         0);`

   return 0;

这很好用(\\\\.\\ 位对于大于 COM9 的端口是必需的,并且也适用于那些高达 COM9 的端口)。问题是我的comport并不总是COM20,所以我想让用户指定它是什么。

以下是我尝试过的一些事情:

#include <iostream>    
#include <windows.h>
#include <string>

int main()

   std::string comNum;
   std::cout << "\n\nEnter the port (ex: COM20): ";
   std::cin >> comNum;
   std::string comPrefix = "\\\\.\\";
   std::string comID = comPrefix+comNum;

   HANDLE hSerial;

   hSerial = CreateFile( comID,
                         GENERIC_READ | GENERIC_WRITE,
                         0,
                         0,
                         OPEN_EXISTING,
                         FILE_ATTRIBUTE_NORMAL,
                         0);`

   return 0;

这不会编译并返回错误:error C2664: 'CreateFileW' : cannot convert parameter 1 from 'std::string' to 'LPCWSTR'

我认为也许指定 CreateFileA 会起作用,但这给出了基本相同的错误。

我也试过了:

/*
everything else the same
*/   

hSerial = CreateFile( TEXT(comID),
                      GENERIC_READ | GENERIC_WRITE,
                      0,
                      0,
                      OPEN_EXISTING,
                      FILE_ATTRIBUTE_NORMAL,
                      0);`

也不编译并返回:error C2065: 'LcomID' : undeclared identifier

我不是什么专家,但我已经在这方面工作了一段时间。有人可以告诉我如何替换 L"\\\\.\\COM20" 以使用户可以指定 comport 并且 CreateFile 仍然可以工作吗?谢谢!

【问题讨论】:

【参考方案1】:

您可以使用std::wstringstd::wcinstd::wcout 直接在“unicode 字符串”中执行输入,也可以查看微软的conversion functions。

如果您选择第一个选项(推荐),您仍然需要使用c_str() 函数来访问LPCWSTR 值(指向const wchar_t 的指针)。

示例解决方案(也不使用CreateFileW 语法,以防止UNICODE 宏出现问题):

#include <iostream>    
#include <windows.h>
#include <string>

int main()

   std::wstring comNum;
   std::wcout << L"\n\nEnter the port (ex: COM20): ";
   std::wcin >> comNum;
   std::wstring comPrefix = L"\\\\.\\";
   std::wstring comID = comPrefix+comNum;

   HANDLE hSerial;

   hSerial = CreateFileW( comID.c_str(),
                     GENERIC_READ | GENERIC_WRITE,
                     0,
                     0,
                     OPEN_EXISTING,
                     FILE_ATTRIBUTE_NORMAL,
                     0);`

   return 0;

【讨论】:

我遇到了同样的问题。这解决了它。谢谢!【参考方案2】:

如果你想继续使用std::string,那么在调用CreateFileA()时使用它的c_str()方法,例如:

hSerial = CreateFileA( comID.c_str(), ...);

【讨论】:

+1,这足以解决所述问题(串行端口名称)。【参考方案3】:

作为附加参考,请查看 ATL 转换宏(例如:CA2CW 等)。这些(如果使用得当)可以处理几乎所有简单的内联转换案例,几乎没有大惊小怪。

在您的示例中,您可以使用 std::string,然后使用:

CreateFile( CA2CT( comID.c_str() ), ... );

【讨论】:

【参考方案4】:

如果(出于某种原因)您决定继续使用 ANSI 字符串,请查看 MultiByteToWideChar 函数。但是 ANSI 字符串已经过时了。

【讨论】:

【参考方案5】:

我最近遇到了这个问题。我只是禁用了 Unicode,因为 Unicode 完全超出了此应用程序的范围。

【讨论】:

您不能禁用 Unicode。它是 Windows 的本机字符集。您可能选择使用包装函数,例如CreateFileA。你应该知道他们总是将他们的参数转换为 Unicode(在你的控制之外),然后调用 Unicode 等价物。 @MSalters: #undef UNICODE 然后关闭各种宽字符编译设置。 这实际上并没有禁用 Unicode。 #undef 导致CreateFile 被#定义为CreateFileA,正如我所怀疑的那样。这仍然是 CreateFileW 的包装。此类#defines 不会禁用*W 函数。较新的 API,包括 COM,不受此 #define 影响;它们始终是 Unicode。因此,如果您不想处理两个字符集,请仅选择 Unicode。如果您选择 ANSI,则必须始终考虑它如何在幕后与 Unicode 交互。【参考方案6】:

这里有关于字符串转换的一般信息:http://www.codeproject.com/KB/string/cppstringguide2.aspx

【讨论】:

以上是关于将字符串转换为 LPCWSTR 以用于 CreateFile() 以寻址串行端口的主要内容,如果未能解决你的问题,请参考以下文章

不能从const char *转换为LPCWSTR

如何将 long 转换为 LPCWSTR?

如何将 CStringW 转换为 LPCWSTR? [复制]

error C2664: “CreateFileW”: 不能将参数 1 从“char *”转换为“LPCWSTR”

char*转LPCWSTR解决方案(转)

error C2440: “=”: 无法从“const char [18]”转换为“LPCWSTR”