windows.h在linux中用什么替,Windows下程序向Linux下移植细节 - wenhm的专栏 - CSDNBlog

2023-05-16

3.2.程序的移植

进行程序移植的过程中碰到的问题较多,但大都主要集中在文件名大小写、路径分隔符、数据类型等方面。

3.2.1Linux和Windows操作系统API差异

Windows下基于MFC的API、基于消息的API、基于注册表的API等在Linux下都是没有的,由于文件系统的差异,和文件系统相关的API也是不可以移植的。

解决方法:程序中不使用上面所列的不可移植的操作系统API,通过使用开源库如PWLIB或ACE中的可移植的类来实现所需的功能。

如:

SYSTEMTIME pTime;

GetLocalTime(&pTime);//为windows独有的API

sprintf(sTemp,"[%02.2d-%02.2d-%02.2d]%02.2d:%02.2d:%02.2d %s(%d)",

pTime.wYear,pTime.wMonth,pTime.wDay,

pTime.wHour,pTime.wMinute,pTime.wSecond,file,lineNum);

改为:

使用pwlib的PTime来实现

PTime curTime;//pwlib中可以跨平台使用的时间类

sprintf(sTemp,"[%02.2d-%02.2d-%02.2d]%02.2d:%02.2d:%02.2d %s(%d)",

curTime.GetYear(), curTime.GetMonth(), curTime.GetDay(),

curTime.GetHour(), curTime.GetMinute(), curTime.GetSecond(), file, lineNum);

3.2.2开发库函数的差异

一些函数在Windows操作系统的VC开发库中有,但Linux下的GLIB C开发库中没有或是名字不一样。

Windows下有而Linux下开发库没有的函数,例如:itoa(int,char*, int)、ltoa(long,char*, int)、ultoa(unsignedlong,char*, int)等。

解决方法1:通过编写相应的代码来实现该函数。

解决方法2:使用Linux下含有类似功能的函数来替换,如itoa()、ltoa()等系列的函数都可以通过sprintf()或snprintf()函数来替换。

替换例子1:

ltoa( confHistb.conflong, caTemp, 10 );

可以替换为:

#ifdefWIN32//windows

ltoa( confHistb.conflong, caTemp, 10 );

#else//linux

sprintf(caTemp, "%d", confHistb.conflong);

#endif

或直接用sprintf(caTemp, "%d", confHistb.conflong);替换即可。

例2:Windows下Sleep()函数对应的Linux下函数为sleep()和usleep(),要特别注意的是Windows下Sleep()为休眠多少毫秒,而sleep()和usleep()分别为休眠多少秒和微妙,所以替换的时候不仅要注意函数的名称不同还要注意单位的不一致。

例3:Windows下stricmp()函数在Linux下对应的为strcasecmp()函数,可以通过宏定义来区分不同平台的代码,也可以在WINTYPES.H文件中加入如下语句:

#define stricmp strcasecmp

通过宏替换来实现。

3.2.3Linux下对文件名大小写敏感

Windows下由于操作系统对文件名大小写不明感,#include语句中文件名的大小写均可以,而Linux操作系统是对文件名大小写敏感的,#include语句中的文件名必须和原文件名大小写一模一样才能找到。

解决方法:#include语句中文件名和原文件名大小写不一致的全部要修改为一致。

3.2.4Linux下路径中各目录的分隔符只能为”/”

Windows下路径的分隔符使用”\”和“/“均可,而Linux下只能使用”\“来作为路径中个目录的分隔符。

解决方法:#include语句中路径的分隔符全部使用“/”。

数据类型

3.2.5程序里不能使用Windows特有的数据类型

例如:FAR PASCAL、HWND、HMENU、HFONT等,因为这些类型在Linux下无法找到替代它们的类型,必然导致程序的不可移植。

3.2.6可以移植的数据类型

有些数据类型是可以通过类型定义来实现的,如CHAR、LONG、INT、INT32、FLOAT、BOOL、VOID、UCHAR、CONST、WINAPI、CALLBACK等,这些类型在Windows下的VC开发库中定义了,但在Linux下没有。

解决方法:可以通过创建一个WINTYPES.H的头文件,将这些类型定义放在该文件里。

编译时加上“-includePATH/WTYPES.H”编译选项即可不用在代码中加入任何“#include”语句而使用WINTYPES.H中的类型,这里的PATH为WINTYPES.H文件所在的路径。示例代码如下:

typedef float FLOAT;

typedef char CHAR;

#define VOIDvoid

#define WINAPI__attribute__((stdcall))

#define CALLBACK__attribute__((stdcall))

3.2.7一些宏定义Windows下有而Linux下没有

有些宏定义如:

#defineMAKEWORD(a, b)((WORD)(((BYTE)(a)) | ((WORD)((BYTE)(b))) << 8))

#defineMAKELONG(a, b)((LONG)(((WORD)(a)) | ((DWORD)((WORD)(b))) << 16))

#defineLOWORD(l)((WORD)(l))

#defineHIWORD(l)((WORD)(((DWORD)(l) >> 16) & 0xFFFF))

#defineLOBYTE(w)((BYTE)(w))

#defineHIBYTE(w)((BYTE)(((WORD)(w) >> 8) & 0xFF))

等在Windows下有,而Linux下没有。

解决方法:在使用到这类宏定义时将相应的宏定义放入WINTYPES.H文件中即可。

3.2.8同名但结构不同的数据类型

Winows下structin_addr结构定义如下:

struct in_addr {

union {

struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;

struct { u_short s_w1,s_w2; } S_un_w;

u_long S_addr;

} S_un;

};

而Linux下structin_addr结构定义为:

struct in_addr

{

__u32 s_addr;

};

解决方法:因在使用这种类型的时候不同操作系统下面的代码不一样,要使用宏定义将不同操作系统下的代码分开。

例:

#ifdefWIN32

ipAdd.S_un.S_addr = address_ip;

#else

ipAdd.s_addr = address_ip;

#endif

宏定义WIN32为Windows下VC编译器自带的一个宏定义,该宏定义在Linux下不存在所以在Windows下和Linux下使用的代码是不同的。

3.2.9Windows下的头文件Linux下名字不同

有些头文件在Windows下和Linux下名字不一样,如strstrea.h在Linux下对应的文件名为sstream或strstream。

解决方法:当发现以后写头文件在Linux下找不到时,查看下是否Linux相应头文件的名字不一样,是否开发库的不同版本头文件不一样,有些开发库如STL开发库由于不断升级会淘汰一些头文件而使用其它的头文件来进行替代。

所以

#include

修改为:

#ifdefWIN32//windows

#include

#else//linux

#include

#include

#endif

3.2.10Windows和Linux下编译器对语言理解的差异

由于编译器的差异也导致要将不同平台下的代码要使用宏定义来区分开,如:

for(int i=0; i< iSize; i++)

语句定义的变量i在Windows下该变量将在for语句执行完后仍有效,而在Linux下变量i只在for语句内部有效出了for语句的范围后就失效了。

解决方法:这种情况是由于编译器对语言语义上的理解不同导致的,只要看下编译的错误信息就可以很快解决,要注意的时要使用宏定义来包含不同平台之间的代码。

3.2.11Linux下编译器检查比Windows下VC的编译器检查更严格

Linux下的编译器检查比Windows下更严格,特别是类型转换检查方面,如:

char strTime=“2004/01/02 14:00:00”;

PTime starttime = strTime;

在windows下编译可以通过,但由于PTime类只有PTime(const PString & str)构造函数,而strTime为char[]类型,虽然在Windows下可以编译通过但在Linux下编译通不过。

解决方法:增加强制类型转换即可。

char strTime=“2004/01/02 14:00:00”;

PTime starttime = Pstring(strTime);

这方面的代码编译错误只要看下编译的错误信息也可以很快就解决。由于是Linux下编译器检查比Windows下严格,所以只要能保证在Linux下编译通过Windows下肯定也能编译通过不用使用宏定义来包含不同平台之间的代码。

四、效果评价

以上所列移植的问题是在进行zxms80项目的CSS(会议调度模块)移植时碰到的,CSS模块采用pwlib的ptlib,mak文件来创建makefile文件,采用了前面所列的解决方法来解决碰到的问题,整个移植过程花了一个月左右。(CSS代码大概40000行左右,使用了Pwlib库、ACE+TAO库、Libodbc++库)

通过借用pwlib的ptlib.mak文件可以快捷的创建自己的makefile文件,创建出来的makefile简单易读。

Windows下程序往Linux下移植主要就是会碰到上面列出来的一些问题,文中为每类问题都进行了举例和提供了相应的解决方案希望对要进行程序平台移植的同仁会有所裨益。

五、推广建议

并不是任何程序都可以轻松进行移植的,只有在设计、开发初期考虑到程序的可移植性,使用了可移植的开发库来进行开发,尽量避免使用和平台相关的代码,这样的程序才能快速、方便的进行移植。

文中描述的移植中碰到的问题和解决方法对于Windows平台下C/C++程序向Linux平台移植均适用,特别是对于使用了pwlib库来进行开发的程序提出了快捷的建立makefile工程文件的方法,并对makefile文件的关键部分进行了解释,最后给出了一个makefile文件的完整范例。即使是没有使用pwlib开发库也可以使用pwlib的相应make文件来构建自己的makefile文件,只是需要将相应编译pwlib库的那部分脚本(common.mak文件中)屏蔽掉就可用于创建任何工程的makefile文件。

只要使用了可移植的开发库来开发大部分代码,移植过程还是比较顺利的,主要是一些如文件名大小写、路径分隔符使用不对等小问题的重复修正,若是使用了很多和Windows Api相关的代码如访问注册表、文件操作的Api则要费些功夫来重写这部分代码了。

通过对程序进行移植操作,一定更能深刻体会写代码时为什么要注意可移植性了,不能一味的为了方便使用简单而不可移植的方法来实现。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

windows.h在linux中用什么替,Windows下程序向Linux下移植细节 - wenhm的专栏 - CSDNBlog 的相关文章

  • 伊迪德信息

    重新定义问题 有什么方法可以获取所连接显示器的序列号吗 我想收集显示器的Eid信息 当我使用 logverbose 选项运行 X 时 我可以从 xorg 0 log 文件中获取它 但问题是 如果我切换显示器 拔出当前显示器 然后插入另一个显
  • 为什么在 Linux 上字符串文字的内存地址与其他字符串文字的内存地址如此不同?

    我注意到字符串文字在内存中的地址与其他常量和变量 Linux 操作系统 非常不同 它们有许多前导零 未打印 Example const char h Hi int i 1 printf p n void h printf p n void
  • 已安装全局 NPM 包但未找到命令

    我已经全局安装了两个 npm 包 下载 https www npmjs com package download and 谜虚拟盒 https www npmjs com package enigmavirtualbox通过命令行 npm
  • 你将如何开始自动化我的工作? - 第2部分

    后续这个问题 https stackoverflow com questions 2796128 how would you start automating my job 在经历了第一波进货 9 小时的复制 粘贴 后 我现在相信我已经满足
  • SidBySide:3rd Party Dll 指的是 MSVCR80.DLL 的两个版本

    我们包含了一个 3rd Party lib DLL 最近在安装时造成了很多麻烦 使用依赖步行者 http www dependencywalker com 我们发现dll本身引用了两个不同版本的 MSVCR80 DLL Version 8
  • NTFS 连接点和符号链接有什么区别?

    在高水平上 两者之间唯一明显的区别NTFS 连接点 http msdn microsoft com en us library windows desktop aa365006 aspx and 符号链接 http msdn microso
  • 如何不断刷新屏幕并实时更新[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我想在linux上写一个C程序 不断刷新屏幕并实时更新 例如类似于top终端中的命令 谁能指出我正确的方向 为了保持它跨终端类型的可移
  • 在Linux中断上下文中运行用户线程

    我正在编写一些定制的应用程序 并允许更改 Linux 内核中的中断处理程序代码 我有一个用户线程正在等待中断发生 如果发生中断 那么我要做的第一件事就是执行该用户线程 有什么办法让它发挥作用吗 Thanks 创建一个字符设备 这就是内核所做
  • Bash 方法的返回值总是模 256

    我有一个 bash 脚本方法 它返回输入值 然而 返回值始终是模 256 的值 我用 google 搜索了一段时间 发现this http www tldp org LDP abs html exitcodes html文章说它总是以 25
  • 64 位大型 malloc

    malloc 失败的原因是什么 尤其是在 64 位中 我的具体问题是尝试在 64 位系统上分配一大块 10GB RAM 该机器有 12GB RAM 和 32GB 交换空间 是的 malloc 是极端的 但是为什么它会成为一个问题呢 这是在带
  • 在 C# 中使用反射列出枚举中的值

    我正在尝试使用反射来列出一个 Visual Studio 解决方案内的各个项目中的一些类的公共成员和方法 我尝试访问的所有类都是 C 的 并且它们都是从 C 类访问的 我用来进行这些调用的代码如下 public void PopulateE
  • 使用 Windows 任务计划程序安排 [Virtualenv 相关] Python 脚本

    I want to schedule a python script to start at 3AM and break at 5PM every weekday However the problem arises when I need
  • Linux shell 脚本中的 while 循环超时

    这工作正常 无限循环 while TRUE do printf done 我在尝试着timeout this while loop与timeout命令 所有这些都不起作用 timeout 5 while TRUE do printf don
  • 让 MongoDB 在 Linux 上监听远程连接

    我已在 Windows 本地计算机上 上成功安装 MongoDB 作为服务 但现在我想将 MongoDb 移动到单独的服务器 所以我将 tarball 解压到网络上的虚拟服务器 运行 Linux 当我从本地计算机使用 PuTTY 连接到服务
  • 为 Windows 98 编译 Qt

    我需要支持 Windows 98 Qt 文档声称这是可能的 但没有说明 Qt 4 6 的分布式二进制文件不能在 Win98 上运行 而且我采样的大多数 Qt 应用程序也不能在 Win98 上运行 对于几个确实在 98 上运行的应用程序 我询
  • 如何使用 sed 仅删除双空行?

    我找到了这个问题和答案 https stackoverflow com questions 4651591 howto use sed to remove only triple empty lines关于如何删除三重空行 但是 我只需要对
  • 在主目录中安装库

    在 Linux Ubuntu 中 我尝试运行一个工具 但它显示错误 库丢失 我无权在系统中安装任何内容 或者根本无法从我的用户帐户执行 sudo 是否可以在我的主目录 没有 sudo 中安装缺少的库 在我的例子中为 libstdc so 6
  • fprintf() 线程安全吗?

    我正在为野人就餐问题的某些变量编写一个 C 解决方案 现在 我创建线程 每个线程都将 FILE 获取到同一个调试文件 在线程内我正在使用 fprintf 进行一些打印 打印的语句不受任何类型的互斥锁等保护 我没有在调试文件中观察到任何交错行
  • 如何更改 Ubuntu 14.04 上的 php-cli 版本?

    我是 Linux 新手 在篡改时破坏了一些 php 设置 如果我执行一个包含以下内容的 php 脚本 phpinfo 它显示 php 版本为 5 6 但通过命令行 如果我运行php v它返回 7 0 版本 我想让两个版本匹配 我怎样才能修复
  • 如何模拟ARM处理器运行环境并加载Linux内核模块?

    我尝试加载我的vmlinux into gdb并使用 ARM 内核模拟器 但我不明白为什么我会得到Undefined target command sim 这是外壳输出 arm eabi gdb vmlinux GNU gdb GDB 7

随机推荐