自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

詳解跨平臺(tái)代碼的3種組織方式

開(kāi)發(fā)
我們?cè)谠创a中也會(huì)遇到一些跨平臺(tái)的問(wèn)題。不同的功能,在不同的平臺(tái)下,實(shí)現(xiàn)方式是不一樣的,如何對(duì)這些平臺(tái)相關(guān)的代碼進(jìn)行組織呢?這篇文章就來(lái)聊聊這個(gè)問(wèn)題。

[[390799]]

一、緣起

在上一篇文章中,分享了一個(gè)跨平臺(tái)的頭文件是長(zhǎng)成什么樣子的,這個(gè)頭文件對(duì)于 windows 平臺(tái)下更有意義一些,因?yàn)橐幚韼?kù)函數(shù)的導(dǎo)入和導(dǎo)出聲明(dllexport、dllimport)。

其實(shí),可以在這個(gè)頭文件的基礎(chǔ)上繼續(xù)擴(kuò)充,以達(dá)到更細(xì)粒度的控制。例如:對(duì)編譯器的判斷、對(duì)編譯器版本的判斷等等。

同樣的,我們?cè)谠创a中也會(huì)遇到一些跨平臺(tái)的問(wèn)題。不同的功能,在不同的平臺(tái)下,實(shí)現(xiàn)方式是不一樣的,如何對(duì)這些平臺(tái)相關(guān)的代碼進(jìn)行組織呢?這篇文章就來(lái)聊聊這個(gè)問(wèn)題。

PS: 文末提供了一個(gè)簡(jiǎn)單的、跨平臺(tái)構(gòu)建代碼示例。

二、問(wèn)題引入

假設(shè)我們寫(xiě)一個(gè)庫(kù),需要實(shí)現(xiàn)一個(gè)函數(shù):獲取系統(tǒng)時(shí)間戳。作為實(shí)現(xiàn)庫(kù)的作者,你決定提供下面的 API 函數(shù):

  1. t_time.h: 聲明接口函數(shù)(t_get_timestamp); 
  2. t_time.c:實(shí)現(xiàn)接口函數(shù); 

下面的任務(wù)就是在函數(shù)實(shí)現(xiàn)中,通過(guò)不同下的 C 庫(kù)或系統(tǒng)調(diào)用,來(lái)計(jì)算系統(tǒng)當(dāng)前的時(shí)間戳。

在 Linux 平臺(tái)下,可以通過(guò)下面這段代碼實(shí)現(xiàn):

  1. struct timeval tv; 
  2. gettimeofday(&tv, null); 
  3. return tv.tv_sec * 1000 + tv.tv_usec / 1000; 

在 Windows 平臺(tái)下,可以通過(guò)下面這段代碼實(shí)現(xiàn):

  1. struct timeb tp; 
  2. ftime(&tp); 
  3. return tp.time *1000 + tp.millitm; 

那么問(wèn)題來(lái)了:怎么把這兩段平臺(tái)相關(guān)的代碼組織在一起?下面就介紹 3 種不同的組織方式,沒(méi)有優(yōu)劣之分,每個(gè)人都有不同的習(xí)慣,選擇適合自己和團(tuán)隊(duì)的方式就行。

此外,這個(gè)示例中只有 1 個(gè)函數(shù),而且比較短小。如果這種跨平臺(tái)的函數(shù)很多、而且都很長(zhǎng),也許你的選擇又不一樣了。

三、三個(gè)解決方案

方案1

直接在接口函數(shù)中,通過(guò)平臺(tái)宏定義來(lái)區(qū)分不同平臺(tái)。

平臺(tái)宏定義(T_LINUX, T_WINDOWS),是在上一篇文章中介紹的,通過(guò)操作系統(tǒng)、編譯器來(lái)判斷當(dāng)前的平臺(tái)是什么,然后定義出統(tǒng)一的平臺(tái)宏定義為我們自己所用:

代碼組織方式如下:

  1. int64 t_get_timestamp() 
  2.     int64 ts = -1; 
  3.      
  4. #if defined(T_LINUX) 
  5.     struct timeval tv; 
  6.     gettimeofday(&tv, null); 
  7.     ts = tv.tv_sec * 1000 + tv.tv_usec / 1000; 
  8. #elif defined(T_WINDOWS) 
  9.     struct timeb tp; 
  10.     ftime(&tp); 
  11.     ts = tp.time
  12.     ts = ts *1000 + tp.millitm; 
  13. #endif 
  14.  
  15.     return ts; 

這樣的方式,把所有平臺(tái)代碼全部放在 API 函數(shù)中了,通過(guò)平臺(tái)宏定義進(jìn)行條件編譯,因?yàn)榇a比較短小,看起來(lái)還不錯(cuò)。

方案2

把不同平臺(tái)的實(shí)現(xiàn)代碼放在獨(dú)立的文件中,然后通過(guò) #include 預(yù)處理符號(hào),在 API 函數(shù)中,把平臺(tái)相關(guān)的代碼引入進(jìn)來(lái)。

也就是再增加 2 個(gè)文件:

  1. t_time_linux.c:存放 Linux 平臺(tái)下的代碼實(shí)現(xiàn); 
  2. t_time_windows.c:存放 Windows 平臺(tái)下的代碼實(shí)現(xiàn); 

(1) t_time_linux.c

  1. #include "t_time.h" 
  2. #include <sys/time.h> 
  3.  
  4. int64 t_get_timestamp() 
  5.     int64 ts = -1; 
  6.      
  7.     struct timeval tv; 
  8.     gettimeofday(&tv, null); 
  9.     ts = tv.tv_sec * 1000 + tv.tv_usec / 1000; 
  10.      
  11.     return ts; 

(2) t_time_windows.c

  1. #include "t_time.h" 
  2. #include <windows.h> 
  3. #include <sys/timeb.h> 
  4.  
  5. int64 t_get_timestamp() 
  6.     int64 ts = -1; 
  7.      
  8.     struct timeb tp; 
  9.     ftime(&tp); 
  10.     ts = tp.time
  11.     ts = ts *1000 + tp.millitm; 
  12.  
  13.     return ts; 

(3) t_time.c

這個(gè)文件不做任何事情,僅僅是 include 其他的代碼。

  1. #include "t_time.h" 
  2.  
  3. #if defined(T_LINUX) 
  4. #include <t_time_linux.c> 
  5. #elif defined(T_WINDOWS) 
  6. #include <t_time_windows.c> 
  7. #else 
  8. int64 t_get_timestamp() 
  9.     return -1; 
  10. #endif 

有些人比較反感這樣的組織方式,一般都是 include 一個(gè) .h 頭文件,而這里通過(guò)平臺(tái)宏定義,include 不同的 .c 源文件,感覺(jué)怪怪的?!

其實(shí),也有一些開(kāi)源庫(kù)是這么干的,比如下面:

方案3

在上面方案2中,是在源代碼中填入不同平臺(tái)的實(shí)現(xiàn)代碼。

其實(shí)可以換一種思路,既然已經(jīng)根據(jù)平臺(tái)的不同、放在不同的文件中了,那么可以讓不同的源文件加入到編譯過(guò)程中就可以了。

測(cè)試代碼是使用 cmake 工具來(lái)構(gòu)建的,因此可以編輯 CMakelists.txt 文件,來(lái)控制參與編譯的源文件。

CMakelists.txt 文件部分內(nèi)容

  1. # 設(shè)置平臺(tái)變量 
  2. if (CMAKE_SYSTEM_NAME MATCHES "Linux"
  3. set(PLATFORM linux) 
  4. elseif (CMAKE_SYSTEM_NAME MATCHES "Windows"
  5. set(PLATFORM windows) 
  6. endif() 
  7.  
  8. # 根據(jù)平臺(tái)變量,來(lái)編譯不同的源文件 
  9. set(LIBSRC  t_time_${PLATFORM}.c) 

這樣的組織方式,感覺(jué)代碼更“干凈”一些。同樣的,我們也可以看到一些開(kāi)源庫(kù)也是這么做的:

四、One More Thing

為了文章的篇幅,以上只是貼了代碼的片段。

我寫(xiě)了一個(gè)最簡(jiǎn)單的 demo,使用 cmake 來(lái)構(gòu)建跨平臺(tái)的動(dòng)態(tài)庫(kù)、靜態(tài)庫(kù)、可執(zhí)行程序。寫(xiě)這個(gè) demo 的目的,主要是作為一個(gè)外殼,來(lái)測(cè)試一些寫(xiě)文章時(shí)的代碼。

在 Linux 平臺(tái)下,通過(guò) cmake 指令手動(dòng)編譯;在 Windows 平臺(tái)下,可以通過(guò) CLion 集成開(kāi)發(fā)環(huán)境直接編譯、執(zhí)行,也可以通過(guò) cmake 工具直接生成 VS2017/2019 解決方案。

已經(jīng)把這個(gè) demo 放在 gitee 倉(cāng)庫(kù)中了,感興趣的小伙伴,請(qǐng)?jiān)诠娞?hào)回復(fù):dg36,即可收到克隆地址。

 

責(zé)任編輯:姜華 來(lái)源: IOT物聯(lián)網(wǎng)小鎮(zhèn)
相關(guān)推薦

2012-07-06 15:00:03

跨平臺(tái)工具MoSync

2012-07-06 15:08:14

跨平臺(tái)工具Netbiscuits

2012-07-06 15:03:43

跨平臺(tái)工具Ideaworks 3Marmalade

2012-06-14 09:42:20

跨平臺(tái)工具AppceleratoTitanium

2012-06-14 09:48:06

跨平臺(tái)工具SeregonDragonRad

2012-06-14 09:57:12

跨平臺(tái)工具IBMWorklight

2012-07-06 13:50:44

跨平臺(tái)工具Adobe Phone

2012-07-06 14:02:25

跨平臺(tái)工具RunRevLiveCode

2012-07-06 15:10:39

跨平臺(tái)工具QtNokia

2024-11-11 08:00:00

2020-02-18 20:00:31

PostgreSQL數(shù)據(jù)庫(kù)

2012-06-14 09:37:17

Ansca MobilCorona跨平臺(tái)工具

2012-07-06 14:56:38

跨平臺(tái)工具Motorola SoRhoMobile

2012-07-06 13:45:21

跨平臺(tái)工具Adobe AirFlex

2020-02-10 15:50:18

Spring循環(huán)依賴Java

2017-09-05 10:20:15

2015-05-04 10:20:25

2016-08-19 08:50:12

SparkWordCountreduceByKey

2019-01-31 08:15:38

物聯(lián)網(wǎng)農(nóng)業(yè)IoT

2010-02-01 10:43:10

C++跨平臺(tái)應(yīng)用
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)