2010-09-24 50 views
3

当使用窗口CreateFile函数寻址串行端口时,我似乎遇到了一点TEXT/UNICODE问题。有人能帮忙指出我的错误吗?将字符串转换为LPCWSTR for CreateFile()以寻址串行端口

我写的VC一个Win32控制台应用程序+ +中使用VS 2008

我可以创建一个句柄来解决串行端口是这样的:

#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的comport是必需的,并且对于那些到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; 
} 

这并不编译并返回错误:错误C2664:“CreateFileW”:无法从“的std :: string”转换参数1' LPCWSTR'

我想也许指定CreateFileA会工作,但那给了基本上相同的错误。

我也试过:

/* 
everything else the same 
*/ 

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

也不会编译和回报:错误C2065:LcomID“:未声明的标识符

我没有太多的专家,但我一直在努力在这一段时间了。有人能告诉我如何替换L"\\\\.\\COM20"用户可以指定comport并使CreateFile仍然可以工作吗?谢谢!

回答

5

您可以使用std::wstringstd::wcin,std::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; 
} 
+0

真棒谢谢! – John 2010-09-24 02:48:50

+0

我遇到了同样的问题。这解决了它。谢谢! – 2014-07-14 02:51:23

0

作为附加参考,看看在ATL转换宏(如:CA2CW等) 。这些(如果使用得当的话)几乎可以处理所有简单的内联转换情况,只需少许大惊小怪。

在您的例子,你可以使用的std :: string,然后使用:

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

如果(出于某种原因)你决定继续与ANSI字符串的工作,然后看看在MultiByteToWideChar功能。但ANSI字符串已经过时了。

0

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

+0

您无法禁用Unicode。这是Windows的本地字符集。您可能选择使用包装函数,例如'CreateFileA'。你应该知道他们总是会将他们的参数转换为Unicode(不受控制),然后调用Unicode的等价物。 – MSalters 2010-09-24 07:47:54

+0

@ MSalters:#undef UNICODE,然后关闭各种宽字符编译设置。 – 2010-09-24 15:44:44

+0

这实际上并不禁用Unicode。正如我怀疑的那样,'#undef'导致'CreateFile'被#defined定义为'CreateFileA'。这仍然是'CreateFileW'的包装。 '* W'函数没有被这样的#defines禁用。较新的API,包括COM_,不受此#define影响;他们总是Unicode。因此,如果您不想处理两个字符集,请选择仅Unicode。如果您选择ANSI,则您必须考虑后台与Unicode的交互方式。 – MSalters 2010-09-27 08:04:37

2

如果你想继续使用std::string,然后调用CreateFileA()时使用其c_str()方法,如:

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

+1,这对于所述问题(串行端口名称)已足够。 – MSalters 2010-09-24 07:44:22