c - CreateFile() 和 CreateFileA() 有什么区别?

标签 c visual-studio serial-port

我正在学习教程 here与串口通信

打开和关闭串口的主要代码如下:

HANDLE hComm;

hComm = CreateFileA((LPCSTR)"COM8",                //port name
    GENERIC_READ | GENERIC_WRITE, //Read/Write
    0,                            // No Sharing
    NULL,                         // No Security
    OPEN_EXISTING,// Open existing port only
    0,               // Non Overlapped I/O              // FILE_FLAG_NO_BUFFERING,            // copied from the MFC version
    NULL);        // Null for Comm Devices

if (hComm == INVALID_HANDLE_VALUE){
    DWORD err = GetLastError();
    printf("Error in opening serial port\n");
    printf("err = 0x%x\n", err);
}
else
    printf("opening serial port successful\n");

CloseHandle(hComm);//Closing the Serial Port

如果我使用 CreateFile() 代码编译正常,但串行端口未打开(我收到 Error in opening serial port 消息)

在玩了一会儿代码后,我发现 CreateFileA() 成功打开串口(我什至发现这个的唯一原因是因为当我用谷歌搜索 CreateFile () 函数 我得到了 CreateFileA() 的 MSDN 定义页作为第一个结果

我用谷歌搜索,但找不到两者之间的区别。我找到了 this ,它说我应该始终 CreateFile() 并且编译器应该完成其余的工作,但它在我的情况下不起作用,只有在我专门使用 CreateFileA() 时才起作用

CreateFile()CreateFileA() 之间有什么区别,我应该在我的程序中使用哪一个来进行基本的串行端口通信?

Windows 10
Visual Studio 2013 速成版

最佳答案

这里需要对 Windows API 进行一些解释:Microsoft 很早就引入了 Unicode。当时,他们决定用 16 位表示 Unicode 字符。我想这在当时是一个有效的决定。因此,Microsoft 平台上的 wchar_t 为 16 位宽,(Unicode) 文本存储在 wchar_t 中——这具有每个字符宽度相等的优点。缺点是处理 char 的现有 API 不再兼容。

如今,使用 32 位 Unicode 代码点,这看起来很傻——Microsoft 平台上的 Unicode 文本使用 UTF-16 编码,因此您有两个缺点:与简单的基于 char 的字符串不兼容 < strong> 和 多字符序列。在许多其他平台上,wchar_t 是 32 位宽,Unicode 要么存储在这些 wchar_t 中,要么在“普通”char 中编码为 UTF-8 >s.

但回到 Microsoft API:为了解决这个问题,他们将所有处理字符串的 API 调用重命名为带有 A 后缀,并引入了第二组相同的调用,采用 wchar_t,后缀为 W 表示 Unicode 变体。根据编译时开关 UNICODE,预处理器将原始名称映射到具有任一后缀的真实名称。

您可能知道,C 语言中的字符串文字具有 char * 类型。要生成 wchar_t * 类型的字符串文字,您需要在它前面加上 L 前缀。为了在设置 UNICODE 时自动执行此操作,提供了另一个宏:_T()。所以你应该在你的代码中做的是将任何字符串文字包装在 _T() 中,它会在 UNICODE 时以 L 为前缀> 已定义。

因此,这一行:

hComm = CreateFileA((LPCSTR)"COM8"

应该改为:

hComm = CreateFile(_T("COM8")

关于 LPCSTRLPWCSTR 的一句话:它们现在等同于 char *wchar_t *。所以类型转换是不必要的。这些名称的原因是向后兼容具有分段内存和“远指针”的古代系统。只要您不需要为 win16 编译代码,就忘掉它们吧。


最后是个人意见:Windows 很早就知道 Unicode(IIRC 已经与 Win95 一起使用)并且它现在是标准的。您不太可能希望针对不支持 unicode 的 Windows 系统。您更有可能想要编写一些可移植代码,然后问题是对 Unicode 的不同处理(wchar_t 在 Windows 上,char 在大多数其他系统上使用 UTF-8, UTF-8 在 Internet 上也占主导地位)。

为此,我更喜欢始终定义 UNICODE,对 Windows API 所需的任何常量字符串使用 wchar_t 字符串文字(例如您的 CreateFile( ) 调用,因此只需在它前面加上 L) 并使用 UTF-8 在内部将所有字符串存储在 char 中,仅在需要将它们传递给Windows API。有两个函数可以进行转换:MultiByteToWideChar()WideCharToMultiByte() .这样,您就可以轻松地为其他使用 UTF-8 的操作系统的 API 编写适配器。

关于c - CreateFile() 和 CreateFileA() 有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51462048/

相关文章:

c - 使用 C 从文件中读取字节

visual-studio - 如何解决... Visual Studio 源代码管理通知 "Projects have recently been added to this solution"

bash - 连续串行数据流上的命令行编号操作

c# - 字节数组未初始化为正确的大小?

c - 单链表的结果不正确

c++ - 代码::阻止问题运行

c - 为什么 LLVM AddressSanitizer 而不是 GCC 在这里给我内存泄漏?

wpf - 如何在 VSIX MEF 扩展中为控件重用 Visual Studio WPF 样式?

c# - 从工具箱拖动控件时 ControlDesigner 未激活

.net - 由于不拥有线程,串行端口读取导致错误