三方庫(kù)移植之NAPI開(kāi)發(fā)[2]C/C++與JS的數(shù)據(jù)類型轉(zhuǎn)換
??想了解更多關(guān)于開(kāi)源的內(nèi)容,請(qǐng)?jiān)L問(wèn):??
??51CTO 開(kāi)源基礎(chǔ)軟件社區(qū)??
在《三方庫(kù)移植之NAPI開(kāi)發(fā)[1]—Hello OpenHarmony NAPI》通過(guò)一個(gè)Hello OpenHarmony NAPI樣例講述了NPAI接口開(kāi)發(fā)基礎(chǔ)知識(shí)。本文在其基礎(chǔ)上修改hellonapi.cpp文件,介紹JS類型和C/C++數(shù)據(jù)類型之間的轉(zhuǎn)換。
- 開(kāi)發(fā)基于最新的OpenHarmony3.2Beta3版本及其對(duì)應(yīng)SDK。標(biāo)準(zhǔn)系統(tǒng)開(kāi)發(fā)板為潤(rùn)和軟件dayu200。
筆者刻苦學(xué)習(xí)了三方庫(kù)NAPI開(kāi)發(fā)的一些皮毛,將學(xué)習(xí)經(jīng)驗(yàn)分享如下:
演示視頻:https://ost.51cto.com/show/18126
通過(guò)本文您將熟悉,通過(guò)NAPI框架:
- 如何獲取JS傳遞過(guò)來(lái)的參數(shù)。
- 如何將JS傳遞過(guò)來(lái)的參數(shù)(NAPI框架已封裝為napi_value類型)轉(zhuǎn)換成C/C++類型值用于計(jì)算。
- 如何將C/C++類型的值轉(zhuǎn)換成JS類型作并返回。
通過(guò)NAPI框架進(jìn)行C/C++與JS數(shù)據(jù)類型的轉(zhuǎn)換
- OpenHarmony NAPI將ECMAScript標(biāo)準(zhǔn)中定義的Boolean、Null、Undefined、Number、BigInt、String、Symbol和Object八種數(shù)據(jù)類型,以及函數(shù)對(duì)應(yīng)的Function類型,統(tǒng)一封裝成napi_value類型,下文中表述為JS類型,用于接收ArkUI應(yīng)用傳遞過(guò)來(lái)的數(shù)據(jù)及返回?cái)?shù)據(jù)給ArkUI應(yīng)用。
ECMAScript是一種由Ecma國(guó)際(通過(guò)ECMA-262標(biāo)準(zhǔn)化的腳本程序設(shè)計(jì)語(yǔ)言。這種語(yǔ)言在萬(wàn)維網(wǎng)上應(yīng)用廣泛,它往往被稱為JavaScript或JScript,所以它可以理解為是JavaScript的一個(gè)標(biāo)準(zhǔn),但實(shí)際上后兩者是ECMA-262標(biāo)準(zhǔn)的實(shí)現(xiàn)和擴(kuò)展。
- 下面通過(guò)擴(kuò)展一個(gè)簡(jiǎn)單的接口——Add(num1, num2)講述具體細(xì)節(jié),接口使用同步方式實(shí)現(xiàn),NAPI的同步方式調(diào)用的擴(kuò)展API代碼處理流程如下圖。
.cpp源碼實(shí)現(xiàn)
- 在《??三方庫(kù)移植之NAPI開(kāi)發(fā)[1]—Hello OpenHarmony NAPI ??》一文的基礎(chǔ)上修改hellonapi.cpp文件,其余文件不變。
- hellonapi.cpp內(nèi)容如下:
.cpp源碼解析
注冊(cè)NAPI模塊、添加接口聲明
接口業(yè)務(wù)實(shí)現(xiàn)C/C++代碼
獲取參數(shù)
- NAPI定義API方法時(shí)的接收參數(shù)為(napi_env, napi_callback_info)
- 其中napi_callback_info為上下文的信息。
- NAPI提供了napi_get_cb_info()方法可從napi_callback_info中獲取參數(shù)列表、this及其他數(shù)據(jù)。
napi_get_cb_info函數(shù)在ohos3.2beta3源碼foundation/arkui/napi/native_engine/native_api.cpp中。
napi_get_cb_info函數(shù)說(shuō)明如下:
- 參數(shù)說(shuō)明:
- [in] env: 傳入接口調(diào)用者的環(huán)境,包含js引擎等,由框架提供,默認(rèn)情況下直接傳入即可。
- [in] cbinfo: napi_callback_info對(duì)象,上下文的信息。
- [in-out] argc: argv數(shù)組的長(zhǎng)度。若napi_callback_info中實(shí)際包含的參數(shù)的個(gè)數(shù)大于請(qǐng)求的數(shù)量argc,將只復(fù)制argc的值所指定數(shù)量的參數(shù)只argv中。若實(shí)際的參數(shù)個(gè)數(shù)小于請(qǐng)求的數(shù)量,將復(fù)制全部的參數(shù),數(shù)組多余的空間用空值填充,并將參數(shù)實(shí)際長(zhǎng)度寫(xiě)入argc。
- [out] argv: 用于接收參數(shù)列表。
- [out] this_arg: 用于接收this對(duì)象。
- [out] data: NAPI的上下文數(shù)據(jù) 返回值:返回napi_ok表示轉(zhuǎn)換成功,其他值失敗。下面的返回napi_status方法一樣。
- 在Add方法中,調(diào)用napi_get_cb_info函數(shù):
JS類型值轉(zhuǎn)換為C/C++類型的值
- 此示例中傳入的參數(shù)是Javascript值類型,被NAPI框架封裝成統(tǒng)一的唯一類型——napi_value類型,為了能夠進(jìn)行計(jì)算,我們需要獲取其對(duì)應(yīng)在C/C++中的類型的值。
- NAPI提供了包括以下方法以便獲取不同類型的值(ohos3.2beta3源碼foundation/arkui/napi/native_engine/native_api.cpp中)
- napi_get_value_double
- napi_get_value_int32
- napi_get_value_uint32
- napi_get_value_int64
- napi_get_value_bool
- napi_get_value_string_latin1(Copies LATIN-1 encoded bytes from a string into a buffer)
- napi_get_value_string_utf8(Copies UTF-8 encoded bytes from a string into a buffer)
- napi_get_value_string_utf16
- napi_get_value_external
- napi_get_value_bigint_int64
- napi_get_value_bigint_uint64
- napi_get_value_bigint_words
- 此示例hellonapi.cpp中使用到了napi_get_value_double方法,函數(shù)定義如下:
參數(shù)說(shuō)明:
- [in] env: 傳入接口調(diào)用者的環(huán)境,包含js引擎等,由框架提供,默認(rèn)情況下直接傳入即可。
- [in] value: 傳入要轉(zhuǎn)換的napi_value類型數(shù)據(jù)對(duì)象(可視為一個(gè)JS對(duì)象)。
- [out] result: 轉(zhuǎn)換出對(duì)應(yīng)類型(double)結(jié)果。 返回值:返回napi_ok表示轉(zhuǎn)換成功,其他值失敗。
獲取參數(shù)的C/C++類型的值前,需要先判斷值的類型,本示例需要判斷傳入?yún)?shù)的JS值必須為number類型
- NAPI框架提供了napi_typeof方法用于獲取指定對(duì)象的類型,其函數(shù)定義如下:
參數(shù)說(shuō)明:
- [in] env: 傳入接口調(diào)用者的環(huán)境,包含js引擎等,由框架提供,默認(rèn)情況下直接傳入即可。
- [in] value: 傳入要轉(zhuǎn)換的napi_value類型數(shù)據(jù)對(duì)象(可視為一個(gè)JS對(duì)象)。
- [out] result: 返回value參數(shù)對(duì)應(yīng)的JS類型。
- napi_valuetype對(duì)應(yīng)了ECMAScript標(biāo)準(zhǔn)中定義的Boolean、Null、Undefined、Number、BigInt、String、Symbol和Object八種數(shù)據(jù)類型,以及函數(shù)對(duì)應(yīng)的Function類型。
- 另外,napi_valuetype還包括了一個(gè)napi_external類型,其表示沒(méi)有任何屬性也沒(méi)有任何原型的對(duì)象。
綜上所述參數(shù)類型判斷及值轉(zhuǎn)換,示例代碼如下:
計(jì)算結(jié)果轉(zhuǎn)換為JS類型并返回
- 計(jì)算的結(jié)果是C/C++類型,需要轉(zhuǎn)換成NAPI node_value類型返回給JS。
- NAPI提供了一些方法以便將C/C++不同類型的值轉(zhuǎn)為node_value類型,返回給JS代碼。例如:
- napi_create_double
- napi_create_int32
- napi_create_uint32
- napi_create_int64
- napi_create_string_latin1
- napi_create_string_utf8
- napi_create_string_utf16
- 以napi_create_double方法為例,函數(shù)定義如下:
參數(shù)說(shuō)明:
[in] env: 傳入接口調(diào)用者的環(huán)境,包含js引擎等,由框架提供,默認(rèn)情況下直接傳入即可。
[in] value: 傳入要轉(zhuǎn)換的double類型數(shù)據(jù)值。
[out] result: 轉(zhuǎn)換出結(jié)果。
ArkUI應(yīng)用實(shí)現(xiàn)代碼
ArkUI應(yīng)用實(shí)現(xiàn)目錄結(jié)構(gòu)。
index.ets內(nèi)容如下:
index.ets
效果圖如下:
index.ets解析
- 參數(shù)說(shuō)明
字段 | 類型 | 說(shuō)明 |
tittle | string | 標(biāo)題 |
message | string | 說(shuō)明 |
tipsNum1 | number | 提示輸入第一個(gè)參數(shù) |
tipsNum2 | number | 提示輸入第二個(gè)參數(shù) |
tipsResult | string | 提示結(jié)果 |
buttonSubmit | string | 計(jì)算按鈕名稱 |
result | string | 結(jié)果 |
num1 | number | 輸入的第一個(gè)數(shù) |
num2 | number | 輸入的第二個(gè)數(shù) |
- 設(shè)置參數(shù)
- 界面實(shí)現(xiàn)
- 綁定事件、關(guān)聯(lián)參數(shù)
兩個(gè)TextInput組件分別綁定onChange事件,并分別關(guān)聯(lián)num1,num2來(lái)記錄輸入的參數(shù)。
- Button組件添加點(diǎn)擊事件,調(diào)用hellonapiu.cpp中的Add方法(調(diào)用js中的add,add和Add已經(jīng)在napi.cpp中綁定)。
- 通過(guò)NAPI框架輸入到C的Add函數(shù)的JS參數(shù)是num1和num2,輸出的JS參數(shù)是result。
@ohos.hellonapi.d.ts接口文檔
總結(jié)
hellonapi.cpp:
index.ets:
??想了解更多關(guān)于開(kāi)源的內(nèi)容,請(qǐng)?jiān)L問(wèn):??