cheerp数据类型包装

简介: 这个文章主要描述在cheerp环境下, js和c++侧数据类型的转换和包装内容。1 基础数据类型首先我们知道javascript是弱类型的脚本语言,开发者在开发的时候不必关注数据的类型和边界,而c++是静态编程语言, 在编译阶段就需要确定类型,在编译器处理的时候可以获得更好的优化。

这个文章主要描述在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)的技术开销要小很多。类型包装也是他性能优化的基础方式之一。

相关文章
|
2月前
|
前端开发 算法 JavaScript
2695. 包装数组
2695. 包装数组
16 0
|
1月前
|
存储 C# 索引
C#学习相关系列之数据类型类的定义(一)
C#学习相关系列之数据类型类的定义(一)
引用传递示例,以及String类型如何传递的原理
大家都知道值传递和引用传递,下面我来通过以一个问题和示例来解决引用类型传递的原理         1)先创建了引用类型Person里面有String name 和int age          2)new 一个对象,把这个对象的值赋给a,再把a赋给Person类型的b
|
4月前
|
JavaScript 前端开发 编译器
TypeScript 中的基础类型:原始类型、对象类型、数组类型、元组类型、枚举类型和联合类型
TypeScript 中的基础类型:原始类型、对象类型、数组类型、元组类型、枚举类型和联合类型
46 1
|
4月前
自定义封装一个方法让这个方法可以判断所有的数据类型并返回
自定义封装一个方法让这个方法可以判断所有的数据类型并返回
15 0
|
JavaScript 前端开发 索引
ES6——类数组转换为数组的几种方法以及for of、forin、for Each的区别
类数组转换为数组的几种方法以及for of、forin、for Each的区别
102 0
1、原始类型与引用类型(区别)
1、原始类型与引用类型(区别)
113 0
|
Java
数据类型的封装类
数据类型的封装类
85 0
|
存储 关系型数据库 MySQL
Mysql存储过程无法传递、转换数组类型参数解决方案
mysql存储过程功能弱问题一直是大家关注的问题,今天讲一下Mysql存储过程无法传递数组类型参数的解决方案。 在很多的情况下,在编写存储过程中往往会用到数组,但是mysql中存储过程传入参数并没有可以直接传入数组的方法。
2676 0