1. 程式人生 > 程式設計 >網易技術乾貨 | 雲信跨平臺C++ SDK開發實戰

網易技術乾貨 | 雲信跨平臺C++ SDK開發實戰

1. 序 言

2018年,Flutter Release正式釋出,將移動端跨平臺開發技術再一次推上風口浪尖。2019年5月,Flutter 1.5正式支援Web開發,而預告中正在開發的Flutter for Desktop以及對於嵌入式的支援,使得Flutter最終目標將不再是移動框架,而是一個跨平臺、多平臺框架。再往前推數年,RN、小程式已經是移動端生產開發中常見的跨平臺開發技術,Electron、Qt也逐漸成為當前桌面端跨平臺應用的首選技術方案。 綜上所述,在客戶端一次編寫,多處執行的大趨勢下,底層SDK服務能力的跨平臺化、多平臺化就顯得更為重要和自然。 雲信SDK提供有iOS/OSX、AOS、Windows、Linux、Unity等常見平臺的支援,從長期的開發維護中得到的經驗,我們認為底層能力的跨平臺化應該解決如下痛點:
  1. SDK介面在各平臺上不統一,包括介面的命名、傳參,對外部開發者不友好。
  2. SDK功能在各平臺上由不同團隊維護,需求需要反覆溝通保障實現上的統一,使得產品迭代速度很慢。
  3. 如果團隊之間沒有有效的溝通,面對同樣的需求和能力,不同的實現方案,測試團隊往往需要設計不同的測試用例,降低了產品迭代效率。
當然,跨平臺開發也有一些不足,比如跨平臺程式碼往往需要引入第三方庫,不如原生平臺編寫的程式碼精簡,遇到與裝置相關的邏輯,還是避免不了需要採用原生程式碼編寫外掛的形式來提供能力等等。

2. 架構介紹

網易雲信C++ SDK目前還只支援Windows平臺,架構設計如下圖:
  • third patry:引入的三方庫。
  • 元件層:SDK開發框架的根基,提供對通訊套接字、本地快取、加/解密、執行緒模型、日誌等基礎功能元件,並對引入的三方庫進行二次封裝。
  • SDK業務實現層:包含了所有SDK業務邏輯的實現,SDK內部執行緒的管理等。
  • SDK介面層:對外暴露SDK各功能介面並提供c++封裝層
nbase整合自chromium開源專案中的一部分,是長期支撐雲信Windows客戶端SDK的基礎庫,包含了基本框架Messageloops,閉包,基本函式庫(file、network等),基本類庫(time,執行緒,定時器等),基本工具庫(log,加解密)等,功能豐富,但是目前僅支援和適配了Windows平臺,並不能很好的支撐其他平臺的開發,因此改進和改造nbase模組是我們跨平臺開發過程中最先考慮的。

3. 跨平臺改造

nbase模組與SDK的實現已深度的耦合,此次改造我們提出了以下幾個目標:
  1. 對上層業務程式碼最少的改動,最好是不要改動。
  2. 可方便更換跨平臺框架,雖然我們選擇了Chromium base作為我們開發框架,但是有可能會隨著Chromium的迭代而對跨平臺框架進行升級/降級,或者為滿足特殊裝置改用其它跨平臺方案。
基於以上兩點考慮,我們把原來nbase模組抽象為框架適配層,將引入的跨平臺框架進行隔離,nbase模組不再實現任務具體功能,只是對跨平臺框架的二次封裝,在最大程度上減少上層程式碼的改動。 改造後的結構圖:

4. 改造之路

4.1. 規範化編碼 除了遵循Google cppguide外我們還整理了與我們SDK開發相關的一些規則:
  1. 標頭檔案: 為了避免某些編譯器編譯失敗,包含的標頭檔案不能使用‘\’,必須全部使用‘/’,不要使用#pragma once ,使用#ifndef _XXX_H_ #define _XXX_H_ #endif,標頭檔案目錄必須從頂層目錄開始,比如’core/core/nim_core.h’。
  2. 名稱空間: [namespace]_BEGIN_DECLS/[namespace]_END_DECLS/ USING_NS_[namespace] 替換原先的名稱空間定義。
  3. 匯出API/類: XXX_EXPORT,匯出的類和函式都要加上這個巨集。
  4. 規範系統定義: OS_WIN/OS_MAC/OS_LINUX/OS_ANDROID/OS_IOS儘量不要直接使用系統自帶的巨集 比如WIN32。
  5. 規範各平臺實現的區別: 通過檔案字尾來區分,比如 platform_device_win.cpp、 platform_device_android.cpp等。
  6. 字串編碼格式的標準化: 使用 std::string/UTF8String/UTF16String/UTF32String。
4.2. base庫的編譯 參考官方檔案Checking out and Building Chromium for Windows chromium.googlesource.com/chromium/sr… chromium原生採用的是Ninja的指令碼編譯,我們並沒有進行直接的生成,而是選擇自行搭建Visual Studio/XCode專案,這樣做的目有兩個:
  1. 方便整合到我們的工程除錯,在開發過程中經常會碰到這樣那樣的問題,所以除錯是必不可少的步驟。
  2. 為了後續對base庫的精簡和可控打下基礎。
目前支援的平臺是Windows/IOS/MacOS三個平臺的編譯,Android/Linux在後續安排開發。編譯步驟基本就是建立新專案,把所有程式碼檔案加入到專案,然後再剔除非該平臺的程式碼檔案,各平臺都適用這步驟。 4.3. extention庫 前面提到把原來nbase模組抽象為框架適配層,我們料想到這個過程無法在一個迭代週期內完成,所以採用分批適配的方式來進行,於是我們又定義了extension庫(同屬nbase名稱空間)來對nbase庫進行抽象,同時對base庫的一些功能進行外圍補充補充。 4.4. 對windows xp的支援 自2014年4月8日之後,微軟不再提供 Windows XP技術幫助,但並不代表使用者可以馬上升級到新的windows作業系統,尤其我們的SDK可能會用於多個行業,對於某些行業使用者來說支援Windows XP是硬性需求,經過幾次討論後,我們發現目前還不可以放棄Windows XP系統,前面提到,我們選擇使用Chromium base (v71.0.3578.98)做為我們跨平臺開發框架,而支援Windows XP系統的chromium版本是“49.0.2623.112”,得益於nbase庫抽象為框架適配層,跨平臺開發框架很快的切換到了chromium 49版本。在編譯支援XP版本時我們需要設定以下幾個配置:
  • Windows SDK 改為使用7.0
  • WINVER = 0x0501
  • PSAPI_VERSION = 1

5. 經驗分享

網易雲信目前已經開發完成並上線了跨平臺C SDK,從一開始的開發跨平臺C SDK到如今的對C++ SDK的跨平臺改造,開發小組也接觸了許多C++開發領域常見並熟識的跨平臺基礎庫,例如stl、boost、Poco、folly等,內部也對幾個基礎庫做過詳細的對比,首先根據我們的SDK業務需求,以及對平臺的需求,如果我們做到跨平臺需要滿足以下幾個最基本的需求: Facebook 的 folly庫應該也是個很好的選擇,但由於時間關係沒有去整理,看介紹,這個庫為了效率重造了很多輪子,估計會有很多詭異的實現,所以並未進入對比範圍。
  • chromium base + net
資料檔案較少,支援我們所需的各種平臺,程式碼較複雜,完整的base庫較大,使用或修改對C++泛型程式設計與模板超程式設計要求較高 Google git :chromium.googlesource.com/chromium
  • Boost
資料檔案豐富,支援我們所需的各種平臺,程式碼還算簡捷,可以有選擇的引入庫,有些功能需要配合其它三方庫來完善,使用起來與STL相差不大 Boost Trac:svn.boost.org/trac10/
  • Poco
資料檔案豐富,支援我們所需的各種平臺,程式碼簡捷,從功能上來說比較全 POCO c++library:pocoproject.org/ POCO docs: poco.sourcearchive.com/

6. TO DO

目前,雲信跨平臺SDK已經支援Windows(xp+)、OSX、iOS平臺,我們計劃2019年Q4完成對Linux部分桌面發行版的開發支援工作,2020年Q1完成對AOS的開發支援工作,後期也會增加對常見的小型裝置的開發支援工作。此外,為了方便開發者快速接入SDK,我們將在2019年Q4上線基於跨平臺SDK封裝的ElectronSDK,2020年上半年上線FlutterSDK。 跨平臺SDK本身很多元件或思想來自於開源社群,未來我們計劃開源跨平臺開發框架,通過回饋開源社群,希望繼續與社群一起打造好玩的“輪子”,大家可以先關注https://github.com/netease-im/phoenix。開源該技術提高了產品團隊與開發者之間的透明度,有助於跨平臺開發的普及,並使開發者能夠參與並對這些開源技術做出持續貢獻。 最後,感謝曾經以及如今還在為網易雲信跨平臺SDK貢獻程式碼的小夥伴們,包括但不限於rg,gg,harrison等等大佬們。

7. 傳送門