Linux 移植 Windows 的 C++ 代码
conio.h 头文件
移植简述
conio.h
不是 C 标准库中的头文件,在 ISO 和 POSIX 标准中均没有定义。conio
是 Console Input/Output(控制台输入输出)的简写,其中定义了通过控制台进行数据输入和数据输出的函数,主要是一些用户通过按键盘产生的对应操作,比如 getch()
函数等等。大部分 DOS、Windows、Phar Lap、DOSX,OS/2 等平台上的 C 编译器提供了此头文件,UNIX 和 Linux 平台的 C 编译器本身通常不包含此头文件。另外在项目开发中,平时主要是使用 conio.h
这个头文件中的 getch()
函数,即读取键盘字符但是不显示出来(without echo),但是含有 conio.h
的代码在 Linux 下无法直接编译通过,因为 Linux 没有这个头文件。但 Linux 平台下完全可以使用 ncurses 替代 conio.h
头文件,ncurses
支持的 API 可以阅读 官方文档。值得一提的是,ncurses
在 Linux 平台实现了 getch()
、scanw()
、getstr()
等函数。
安装依赖
提示
由于 ncurses
不是 Linux 系统默认的库,因此需要安装后才能使用,不同平台的安装命令如下:
- CentOS/Fedora
1 | # yum install -y ncurses ncurses-devel |
- Debian/Ubuntu
1 | # apt-get install -y libncurses5-dev libncursesw5-dev |
案例代码
提示
ncurses.h
与 curses.h
这两个头文件是等价的
1 |
|
编译说明
由于 ncurses
不是 Linux 系统默认的库,因此编译时需要链接到该库,同时还需要在 C++ 的源文件里添加头文件 ncurses.h
,否则编译会失败。
提示
为了可以正常编译使用了 ncurses
的项目代码,不同构建工具的使用说明如下:
若使用 G++ 编译 C++ 项目,则编译命令的示例如下:
1 | # 编译代码 |
若使用 CMake 构建 C++ 项目,则 CMakeLists.txt
配置文件的示例内容如下:
1 | set(CMAKE_CXX_FLAGS "-std=c++11 -lncurses") |
itoa () 函数
移植简述
在 Window 平台里,itoa()
函数可以将整数转换为字符串,其函数的原型如下。Linux 平台中只有 atoi()
函数,并没有对应的 itoa()
函数,但可以使用 sprintf()
或者 snprintf()
函数替代,建议使用更安全的 snprintf()
。
itoa () 函数
函数原型:char *itoa( int value, char *string,int radix)
函数功能:将整数 value
转换成字符串存入 string
指向的内存空间,radix
为转换时所用基数 (保存到字符串中的数据的进制基数)
函数的参数:value
:转换的数据,string
:目标字符串的地址,radix
:转换后的进制数,可以是 10 进制、16 进制等,范围必须在 2-36 之间
snprintf () 函数
头文件:#include <stdio.h>
函数原型:int snprintf(char *str, size_t size, const char *format, ...)
函数功能:将可变参数 ...
按照 format
格式化成字符串,然后将其复制到 str
中
函数参数:str
:目标字符串,size
:拷贝字节数(Bytes),format
:格式化字符串,...
可变参数
案例代码
1 |
|
程序运行的输出结果如下:
1 | str = 12, size = 2 |
strcpy_s () 函数
移植简述
在 Window 平台上,strcpy_s()
函数存在于 #include <cstring>
头文件中。Linux 平台没有该函数,但可以使用 Safe C Library 替代实现。Safe C Library
这个库是在 libc
的基础之上实现了安全的 C11 Annex K 函数,这些函数是它们所缺少的,可以帮助缓解不断增加的安全攻击,特别是缓冲区溢出。
安装依赖
提示
- 由于
Safe C Library
不是 Linux 系统默认的库,因此需要安装后才能使用,其默认的安装目录如下 /usr/local/lib/
:包含静态库和动态链接库文件/usr/local/include/libsafec
:包所有含头文件
1 | # 下载文件(这里下载的不是源码压缩包) |
值得一提的是,Safe C Library
编译后会单独生成静态库文件 /usr/local/lib/libsafec-3.6.0.a
和动态链接库文件 /usr/local/lib/libsafec-3.6.0.so.3.0.6
,其中的 3.6.0
是指版本号。
案例代码
提示
strcpy_s()
函数在Safe C Library
里的safe_str_lib.h
头文件中声明
1 |
|
编译说明
由于 Safe C Library
不是 Linux 系统默认的库,因此编译时需要链接到该库,同时还需要在 C++ 的源文件里添加头文件 <libsafec/safe_str_lib.h>
,否则编译会失败。
提示
- 为了可以正常编译使用了
Safe C Library
的项目代码,不同构建工具的使用说明如下所示 - 可以将上面构建生成的
libsafec-3.6.0.a
静态库文件和.h
头文件都拷贝到项目里,这样就可以方便在不同的 Linux 系统编译和运行项目,不用每次切换系统时都要重新安装Safe C Library
若使用 G++ 编译 C++ 项目,则编译命令的示例如下,请自行更改库文件的版本号:
1 | # 编译代码 |
若使用 CMake 构建 C++ 项目,则 CMakeLists.txt
配置文件的示例内容如下,请自行更改库文件的版本号:
1 | link_libraries(/usr/local/lib/libsafec-3.6.0.a) |
函数可变参数宏
移植简述
在 Windows 平台与 Linux 平台,函数可变参数宏定义的语法是不一样的。
案例代码
- Windows 平台的函数可变参数宏定义的写法如下,使用的是
__VA_ARGS__
1 | FILE* logfile = fopen("syslog.txt", "w"); |
- Linux 平台的函数可变参数宏定义写法如下,使用的是
##__VA_ARGS__
1 | FILE* logfile = fopen("syslog.txt", "w"); |