cheerp數據類型包裝

這個文章主要描述在cheerp環境下, js和c++側數據類型的轉換和包裝內容。

1 基礎數據類型

首先我們知道javascript是弱類型的腳本語言,開發者在開發的時候不必關注數據的類型和邊界,而c++是靜態編程語言, 在編譯階段就需要確定類型,在編譯器處理的時候可以獲得更好的優化。

我們都知道js所擁有的數值類型,(int,uint,float,double)默認不區分都是double類型存儲,這點和lua很相似。

在一般堆棧機下,如果使用函數調用會有大量的push,pop指令來獲取傳遞的參數,還要在內部進行根據類型包裝成可識別的類型。

cheerp的內存模型是平坦的,目標如果不是wasm的話, 是和js一致的,可以直接調用(翻譯成javascript,不需要push,pop這種指令)。

在cheerp環境下如果交織javascript和c++代碼, cheerp會通過位移移除來替我們處理類型, 比如int類型,用js的Number左移兩位來標識。我們可以不關心這些基礎數據的轉換。

2複合數據類型

如果是js模式,cheerp會將js對象轉換成struct,或者是class類的映射,默認不推薦使用動態結構。 首先要在cheerp側擁有對應的結構定義,才能獲取和寫入屬性。
從js側生成庫給c++使用:
比如公開一個函數到c++

function window_base64_encode(s) {
        return window.btoa(s);
  }

我們在c++裏定義

String * window_base64_encode(String *);

cheerp 會自動給我們生成函數調用參數的原型,並切映射到js側.
如果是傳輸的對象我們可以使用Object* 來標識js側的對象。

Object * window_getData(String * );

如果是wasm模式,cheerp會嚴格遵守c++標準,對數據進行轉換。
如果要傳輸複合類型的數據,比如說對象那麼我們需要用struct對基礎數據進行包裝.而不是直接使基礎類型.

struct Sub {
    int age ;
};

struct Data {
    char hellow [20];
    int age ;
    struct Sub c;
};

等同於{age:20, c:{age:21},hellow:"cheerp"}

從c++調用js:

//JSExportAPI::test();
    uint8 Indata[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
    for(char i = 0; i < 16; i++) {
        Indata[i] = i; ///用例
    }
    
    JSExportAPI::myJsSayHello(Indata); ///wasm調用js
    for(char i = 0; i < 16; i++) {
        std::cout  << (*Indata+i)<< endl; //結果
    }

從js調用c++

int myCppSayHello(Data a) {
    cout << "hellow i am from cpp " <<endl;
    cout  <<"hellow="<< a.hellow <<endl;
    cout  <<"age="<< a.age <<endl;
    cout  <<"sub.age="<< a.c.age <<endl;
    return 0;
}
class [[cheerp::genericjs]] JSExportAPI {
    public:
    JSExportAPI() {
    }
    
    static void myJsSayHello (uint8 * buffer) {
        Uint8Array * t = (Uint8Array *)cheerp::MakeArrayBufferView(buffer);
        auto array = cheerp::makeArrayRef(t);

        for( int i = 0 ; i < array->get_length(); i++ ) {
            array[i] = array[i] + 100 ;
            *(buffer+i) = array[i];
        }
        
        struct Data d ;
        d.age = 20;
        d.c   = {21};
        memcpy(d.hellow ,"cheerp", 7);
        myCppSayHello(d);///js調用wasm
    }
};

[[cheerp::genericjs]] 字段是生成js模式的代碼。

無論是js到c++還是c++到js, cheerp轉換的開銷比一般的(ffi)的技術開銷要小很多。類型包裝也是他性能優化的基礎方式之一。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章