stricmp linux 头文件,Windows下程序向Linux下移植细节

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则要费些功夫来重写这部分代码了。

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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值