将 Win32 串行 (RS232) 通信移植到 POSIX

Porting Win32 serial (RS232) comms to POSIX

目前我正在将 Win32 应用程序移植到 POSIX。该软件本身已有几十年历史,用于更新专有机器。

虽然大多数功能相对容易替换为简单的宏和一些调用 POSIX 函数的较小函数,但事实证明 RS232 comms-related 功能很困难。

应用程序使用这些函数通过 RS232 进行通信:

BOOL GetCommState(HANDLE comPort, DCB* dataControlBlock);

BOOL SetCommState(HANDLE comPort, DCB* dataControlBlock);

BOOL GetCommTimeouts(HANDLE comPort, LPCOMMTIMEOUTS comTimeouts);

BOOL SetCommTimeouts(HANDLE comPort, LPCOMMTIMEOUTS comTimeouts);

BOOL SetCommMask(HANDLE comPort, DWORD eventMask);

BOOL GetCommMask(HANDLE comPort, LPDWORD eventMask);

BOOL WaitCommEvent(HANDLE comPort, LPDWORD eventMask, LPOVERLAPPED overlapped);

连同以下结构:

typedef struct _DCB { /*...*/ } DCB, *LPDCB;

typedef struct _COMMTIMEOUTS { /*...*/ } COMMTIMEOUTS, *LPCOMMTIMEOUTS;

搜索的时候看到了thislink,其中提到了termios.h和sys/select.h,但是这些headers的结构太过分了我喜欢的不同。提到使用 Wine 的其他答案,由于应用程序要移植到的硬件,这根本不是一个选项。

如果可能,我想实现一个更简单的解决方案并保留应用程序当前使用的结构 - 试图保留所有内容 cross-compatible。

有办法实现吗?
还是我坚持了应用程序的 re-writing 总部分?

根据您的应用程序的复杂程度,我看到了两种可能的解决方案:

  1. 将 Win32 调用替换为等效的 POSIX 调用,如评论中提到的 P__J__。如果你这样做,等效的调用可能会遵循以下行:

GetCommState : tcgetattr

SetCommState : tcsetattr

Get/SetCommTimeouts :您仍将使用 tcsetattr 设置此项,修改 struct termios

中的 c_cc[VTIME] 条目

Set/GetCommMask :不幸的是,POSIX API 没有与此功能等效的功能。如果需要关心控制信号(CTS、DSR、RING),需要循环读取线路状态。如果你只关心读取返回的字节,你不需要担心这个。

WaitCommEvent :POSIX 上的等价物是 select(旧式)或 poll(更现代)。与上面的 CommMask 类似,select/poll 将 return 当有数据要读取时,而不是当控制线更改时。

  1. 如果您不想自己尝试解决跨平台问题,可以使用几个具有跨平台能力的库(C 语言)。这是一个快速列表:

..我所知道的就这些了。我所知道的所有其他库都是针对 C++ 的。