Windows下程式向Linux下移植細節
【摘要】
根據zxms80專案的會議排程模組移植的經驗,本文提出了Windows平臺上程式向Linux下移植所碰到的一些典型問題,並舉例給出了相應的解決方法,文中還描述了使用pwlib庫時makefile檔案的編寫方法,該方法也適用於不使用pwlib庫開發時的一般情況,供要進行移植的同仁參考之用。
一、問題的提出
由於Linux作業系統原始碼公開是的,開發庫等輔助工具都是原始碼公開的,這樣就減少了程式的不可預知性,而且出現錯誤可以大家一起修正、完善,而Windows平臺下所有的作業系統Api就給了個介面,即使出現莫名奇妙的錯誤也只能望著介面興嘆了。再加上Linux作業系統本身和它上面的許多工具軟體是免費的,更是吸引了更多的公司和程式開發人員將程式開發轉向Linux。
在程式跨平臺的移植過程中,將存在作業系統API的不同、檔名大小寫識別不同、路徑分隔符不同、不同開發平臺資料型別的不一致等較一般性的問題。對於這些一般性的問題怎樣很好的來解決呢?Linux下的工程都是使用makefile檔案來管理的,怎樣編寫出相應的makefile檔案呢?這些問題都是本文後面將要闡述的。
二、解決思路
文中還描述了使用pwlib庫時makefile檔案的編寫方法,對於使用了pwlib庫進行開發的程式能快捷的建立makefile工程檔案,避免了自己手動書寫makefile的繁雜工作。
特別是<3.2.6可以移植的資料型別>一節中對於不同開發平臺資料型別的不一致提出了一個簡捷通用的解決方法,不用修改源程式中任何程式碼即可在Linux下使用Windows開發平臺上的一些資料型別。
三、實踐情況
3.1.Makefile的編寫
具體makefile檔案的編寫規則可以檢視make的man
下文將著重介紹使用pwlib開發庫的工程的makefile的編寫,但對於其它工程只需將common.mak檔案中對pwlib庫進行編譯的指令碼去掉也可適用。
3.1.1使用pwlib開發庫的工程的makefile的編寫
PWLib是Portable
Windows Library的縮寫,翻譯為輕便的Windows類庫.PWLib採用C++編寫,設計初衷是為了能讓Openh323在Windows和Unix的X-Windows下執行,
檢視Pwlib的主目錄下/samples/hello_world/目錄下例子程式的makefile檔案可以發現該Makefile檔案內容如下:
# Simple makefile for the hello world program
PROG
SOURCES = hello.cxx
ifndef PWLIBDIR
PWLIBDIR=$(HOME)/pwlib
endif
include $(PWLIBDIR)/make/ptlib.mak
# End of Makefile
實際上就是使用了Pwlib庫的ptlib.mak檔案,編譯時需要的標頭檔案,相應的編譯選項都在ptlib.mak檔案中設定好了。
我們只需在該makefile檔案所在目錄下,命令列輸入make all命令即可編譯出程式的Release版本和Debug版本,它們分別放在當前目錄的obj_linux_x86_r和obj_linux_x86_d子目錄下。
下面對該makefile中的內容進行解釋:
l
l
l
3.1.2深入分析ptlib.mak檔案
分析ptlib.mak檔案,它的內容如下;
ifndef PWLIBDIR
PWLIBDIR=$(HOME)/pwlib
endif
include $(PWLIBDIR)/make/unix.mak
include $(PWLIBDIR)/make/common.mak
也就是ptlib.mak包含了另兩個檔案unix.mak和common.mak檔案,其中unix.mak為定義編譯選項變數的檔案,編譯規則放在common.mak檔案中。
通過對這兩個檔案的分析,歸納出一些我們寫makefile檔案要用到的一些變數,列出如下:
l
l
l
l
l
3.1.3加入新的編譯規則
common.mak檔案中只對*.c和*.cxx的原始檔定義了編譯規則,而一般windows下程式大多都使用了.cpp來作為C++原始檔的字尾。
怎樣加入對於.cpp字尾的原始檔的編譯規則呢,這需要修改pwlib的common.mak檔案,具體步驟如下:
在vpath %.cxx $(VPATH_CXX)語句後面加入如下語句:
$(OBJDIR)/%.o : %.cpp
SRC_OBJS := $(SRC_OBJS:.cpp=.o)
SRC_DEPS := $(SRC_DEPS:.cpp=.dep)
$(DEPDIR)/%.dep : %.cpp
3.1.4一個makefile範例
3.2.程式的移植
3.2.1Linux和Windows作業系統API差異
Windows下基於MFC的API、基於訊息的API、基於登錄檔的API等在Linux下都是沒有的,由於檔案系統的差異,和檔案系統相關的API也是不可以移植的。
解決方法:程式中不使用上面所列的不可移植的作業系統API,通過使用開源庫如PWLIB或ACE中的可移植的類來實現所需的功能。
如:
SYSTEMTIME pTime;
GetLocalTime(&pTime);
sprintf(sTemp,"[.2d-.2d-.2d].2d:.2d:.2d %s(%d)",
pTime.wYear,pTime.wMonth,pTime.wDay,
改為:
使用pwlib的PTime來實現
PTime curTime;
sprintf(sTemp,"[.2d-.2d-.2d].2d:.2d:.2d %s(%d)",
3.2.2開發庫函式的差異
解決方法1:通過編寫相應的程式碼來實現該函式。
解決方法2:使用Linux下含有類似功能的函式來替換,如itoa()、ltoa()等系列的函式都可以通過sprintf()或snprintf()函式來替換。
替換例子1:
可以替換為:
#ifdef
#else
#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下沒有。
解決方法:可以通過建立一個
編譯時加上“-include
typedef float FLOAT;
typedef char CHAR;
#define VOID
#define WINAPI
#define CALLBACK
3.2.7一些巨集定義Windows下有而Linux下沒有
有些巨集定義如:
#define
#define
#define
#define
#define
#define
等在Windows下有,而Linux下沒有。
解決方法:在使用到這類巨集定義時將相應的巨集定義放入WINTYPES.H檔案中即可。
3.2.8同名但結構不同的資料型別
Winows下struct
struct in_addr {
};
struct in_addr
{
__u32 s_addr;
};
解決方法:因在使用這種型別的時候不同作業系統下面的程式碼不一樣,要使用巨集定義將不同作業系統下的程式碼分開。
例:
#ifdef
#else
#endif
巨集定義WIN32為Windows下VC編譯器自帶的一個巨集定義,該巨集定義在Linux下不存在所以在Windows下和Linux下使用的程式碼是不同的。
3.2.9Windows下的標頭檔案Linux下名字不同
有些標頭檔案在Windows下和Linux下名字不一樣,如strstrea.h在Linux下對應的檔名為sstream或
解決方法:當發現以後寫標頭檔案在Linux下找不到時,檢視下是否Linux相應標頭檔案的名字不一樣,是否開發庫的不同版本標頭檔案不一樣,有些開發庫如STL開發庫由於不斷升級會淘汰一些標頭檔案而使用其它的標頭檔案來進行替代。
#include
修改為:
#ifdef
#else
#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
解決方法:增加強制型別轉換即可。
char strTime=“2004/01/02 14:00:00”;
PTime starttime = Pstring(strTime);
這方面的程式碼編譯錯誤只要看下編譯的錯誤資訊也可以很快就解決。由於是Linux下編譯器檢查比Windows下嚴格,所以只要能保證在Linux下編譯通過Windows下肯定也能編譯通過不用使用巨集定義來包含不同平臺之間的程式碼。
四、效果評價
以上所列移植的問題是在進行zxms80專案
通過借用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則要費些功夫來重寫這部分程式碼了。
通過對程式進行移植操作,一定更能深刻體會寫程式碼時為什麼要注意可移植性了,不能一味的為了方便使用簡單而不可移植的方法來實現。
參考資料
1.
2.
http://www.us1.openh323.org/。
相關文章
- Windows下程式向Linux下移植實踐2-草原之狼-搜狐部落格WindowsLinux
- 關於WINDOWS平臺下RMAN備份移植Windows
- Socket相關程式:從Windows移植到LinuxWindowsLinux
- linux下QT在windows下執行LinuxQTWindows
- linux下rac環境下刪除節點Linux
- Linux 下匿名訪問windows 下的ftpLinuxWindowsFTP
- linux下和windows下如何防止php***薦LinuxWindowsPHP
- Windows下kill oracle程式WindowsOracle
- Onvif開發之Linux下gsoap的使用及移植Linux
- Linux下關於互斥鎖及同步的移植(一)Linux
- Linux下關於互斥鎖及同步的移植(二)Linux
- linux下和windows下如何防止php木馬LinuxWindowsPHP
- Linux下udev詳細介紹Linuxdev
- 向嵌入式Linux移植實時裝置驅動程式(轉)Linux
- Linux下關於互斥鎖及同步的移植(一)薦Linux
- windows環境下memcache配置方法 詳細篇Windows
- Windows 64位下安裝Redis詳細教程WindowsRedis
- Linux 下安裝subversion 詳細指南Linux
- Linux下的程式Linux
- Windows環境下安裝LinuxWindowsLinux
- 求助 windows下引導linux(轉)WindowsLinux
- 在Windows下啟動Linux(轉)WindowsLinux
- Windows下的Memcache安裝 linux下的Memcache安裝WindowsLinux
- linux與windows雙系統時,linux下耳機使用正常,windows下耳機卻沒聲音LinuxWindows
- Linux下GoldenGate單機雙向同步LinuxGo
- Linux下GoldenGate單機單向同步LinuxGo
- Windows下RMAN備份程式碼Windows
- Solaris下Domino資料的移植(轉)
- 計算機程式的思維邏輯 (37) - 泛型 (下) - 細節和侷限性計算機泛型
- (轉)windows環境下rac節點時間同步方法Windows
- linux下使用windows標頭檔案LinuxWindows
- 在Linux下使用DOS/Windows磁碟(轉)LinuxWindows
- linux下的程式管理Linux
- A20 Linux 配置細節Linux
- 物件導向(下)物件
- 物件導向--下物件
- windows10下載安裝Git教程[超詳細]WindowsGit
- 最新MT6739移植資料下載