使用OpenHarmonyNDK移植三方庫Speexdsp
NDK (原生開發套件) 是一套工具,使開發者能夠在 OpenHarmony hap應用中使用 C/C++ 代碼。它提供了一系列的工具可以幫助開發者快速的開發C/C++的動態庫、靜態庫和可執行文件。
OpenHarmony 應用開發的Native C++開發方式就要依賴NDK。NDK被包含在OpenHarmony SDK中。可以在DevEco Studio使用 NDK 將 C/C ++ 代碼編譯到so庫中,然后使用 DevEco Studio 的構建插件hvigor-ohos-plugin將so庫打包到 Hap 中。ArkTS代碼隨后可以通過NAPI框架調用SO庫中的函數。
深開鴻郭岳峰老師開發的OCRDemo就通過NAPI調用了C++的三方庫Tesseract的能力,而這個庫本身還依賴leptonica、libjpeg、libpng、libtiff等C/C ++ 等四方庫。如果重新編寫build.gn移植到OpenHarmony,工作量巨大。
Tesseract (Apache 2.0 License)是一個可以進行圖像OCR識別的C ++ 庫
OpenHarmony集成OCR三方庫實現文字提取
一、編寫build.gn與編寫CMakeLists.txt移植到OpenHarmony兩者的區別
1、編譯環境不同,編譯工具
編寫build.gn方式,編譯環境是在OpenHarmony源碼中,編譯時使用到的是源碼中的編譯工具。
編寫CMakeLists.txt的移植方式實際上是Native C++應用開發方式的一種,并且NDK是SDK的一部分,編譯so時候實際上使用的是NDK的編譯工具。
2、so安裝的地方不一樣
編寫build.gn方式,三方庫編譯出來的so和測試用例可以打包進入OpenHarmony固件中。
編寫CMakeLists.txt方式,編譯出來的實際上會被打包進入hap應用中,hap再安裝到OpenHarmony操作系統上完成三方庫so能力的調用。
3、編寫CMakeLists.txt比編寫build.gn更容易
build.gn總有各種各樣的編譯器標志要加入以消除編譯報錯,開發者學習成本比較高
CMakeLists.txt方式開發者則相對熟悉,對于原生庫就是camke構建的三方庫,只需要對原生庫已有的CMakeLists.txt做少量修改,比如刪除與其他操作系統有關的部分(筆者說的就是AOSP)。
二、使用OpenHarmony的NDK工具移植Speexdsp到Speexdsp
在windows端的IDE上調用NDK。
創建Native C++工程,但是先不寫NAPI和ArkTS的部分,先為C/C ++的三方庫編寫CMakeLists.txt(如果三方庫本身就是cmake構建的,但也要對CMakeLists.txt進行少量的修改,詳細請參考該樣例 https://gitee.com/openharmony-sig/knowledge_demo_temp/tree/master/FA/OCRDemo)。 然后編譯hap應用來調用SDK中的NDK工具。
三、創建Native C++工程使用SDK中的NDK工具
創建Native C++工程參考:三方庫移植之NAPI開發[3]通過IDE開發NAPI工程
1、打開IDE Deveco Studio,創建一個Native C++工程。
2、SDK選擇API9,model選擇Stage。新建的Native C++工程有一個默認的hello world教程。
將Speexdsp加入Native C++工程,在庫中編寫頂層CMakeLists.txt生成動態庫。
將speexdsp源碼移動到Native C++工程entry\src\main\cpp目錄,cpp目錄專門用于存放C/C ++代碼。
刪除Speexdsp中無關的代碼讓代碼結構簡潔。Speexdsp中有一些無關的代碼,例如和win32、macO上運行的有關代碼,甚至還有塞班系統symbian上的代碼。(不管了先刪除,不知道Speexdsp的開源協議允不允許筆者這樣做,但是看著亂亂的目錄結構,筆者希望這樣讓自身的思路清晰一些。)
編寫頂層在CMakeLists.txt生成動態庫。
在庫中編寫底層CMakeLists.txt生成可執行文件,用來驗證so庫是否運行正常。
在.c源文件目錄添加CMakeLists.txt用來編譯出可執行文件,用來驗證使用NDK移植三方庫到OpenHarmony標準系統是否成功。如下:
在庫外的CMakeLists.txt中添加代碼使能speexdsp編譯。
新建的Native C++工程是有一個默認的Hello World模板的,在entry\src\main\cpp目錄下有一個CMakeLists.txt,需要在其中添加代碼使能speexdsp編譯。
如果不添加代碼,則speexdsp的動態庫和可執行用例編譯不出來。
執行編譯命令編譯動態庫和測試用例。
在IDE上方工具欄選擇編譯hap進行so和測試用例的編譯。
編譯結果在entry\build\default\intermediates\cmake\default\obj目錄下。
為什么會IDE中的NDK會編譯出64位和32位的動態庫和可執行文件呢?因為OpenHarmony操作系統有32位和64位,這樣是為了hap能在不同位數的OpenHarmony版本上運行。
根據32位和64位的OpenHarmony版本推送相應的so和可執行文件到開發板上。
如何分辨開發板上OpenHarmony版本是64位還是32位?和linux的方式是一樣。用getconf WORD_BIT和getconf LONG_BIT獲得word和long的位數。64位系統中分別得到32和64。32位系統中分別得到32和32。
筆者開發板上燒錄的是32位的OpenHarmony Beta5版本。
因此需要將Native C++工程目錄下的entry\build\default\intermediates\cmake\default\obj\armeabi-v7a中的libspeexdsp.so和testdenoise、testecho、testjitter、testresample、testresample2推送到設備端的data目錄。
通過與ohos版本匹配的hdc_std工具,將編譯生成的庫以及測試用的可執行文件推送到開發板的data目錄。
執行testdenoise可執行文件(其它測試用例的執行請參考 移植speexdsp到OpenHarmony標準系統⑤)。
通過分析testdenoise.c源碼,執行測試程序時需要指定一份輸入的不為空的8000Hz的input.pcm音頻,并且需要指定一份空的輸出的output.pcm音頻。rk3568上運行,執行語句如下:
測試結果:對比輸入的input.pcm和輸出的outpu.pcm的波形圖和聲譜圖,噪聲已經被消除。pc端和rk3568開發板運行testdenoise可執行程序效果一致。可執行文件運行成功,使用OpenHarmonyNDK移植三方庫Speexdsp成功。
知識點附送
AIP8的應用如何更改為API9支持64位版本。
API8只支持32位,API9支持32位和64位。
以該PR https://gitee.com/openharmony/applications_app_samples/pulls/759 學習將api8應用適配適配Arm64。
修改build-profile.json5 ,將compileSdkVersion和compatibleSdkVersion屬性由8改為9。
compileSdkVersion指定OpenHarmony應用/服務編譯時的SDK版本。
compatibleSdkVersion指定OpenHarmony應用/服務兼容的最低SDK版本。
修改entry/build-profile.json5,abi添加64位arm64-v8a。
abiFilters用于設置本機的ABI編譯環境。
修改entry/src/main/config.json,設備類型改為默認。
這個pr改動了XComponent/entry/src/main/cpp/common/plugin_common.h文件,plugin_common.h文件和hilog調試的功能有關。
編譯構建子系統如何增加編譯構建arm64選擇。
以該issue https://gitee.com/openharmony/build/issues/I53E9I 來學習。
分別在hb工具和build.sh腳本添加–target-cpu選項。
電源服務子系統支持64位。
https://gitee.com/openharmony/powermgr_power_manager/issues/I55094。
graphic子系統適配64位編譯。
https://gitee.com/openharmony/graphic_graphic_2d/issues/I53720。