使用Emscripten 将c/c++编译成js

背景

最近搞open cv识别物体的项目,因为客户需求,最终决定使用js来实现。

捕获摄像头 是通过navigator.mediaDevices,前提是 ios 需要11以上必须是https, android到还好。

识别物体通过opencv js 。

虽然坎坎坷坷 但是第一版还是上线了 除了https和默认显示后置摄像头(Android的枚举摄像头 根据label判断是否是后置的,IOS 中的facingMode:{exact:"environment"} 是有效的),其它还算顺利。

然后 然后 opencv js 10M 这个大小比较要命。。。

opencv是通过Emscripten 将c编译成js的 

所以打算ctrl+c, ctrl+v 精减下源码,再编译下,将js文件减少到500kb之内是没有问题的。

安装

安装 Emscripten 还是比较简单的 

https://kripken.github.io/emscripten-site/docs/getting_started/downloads.html

git clone https://github.com/juj/emsdk.git

cd emsdk

git pull

emsdk install latest

我是windows下,安装的时候 下载LLMV的 很慢总失败,后来挂了代理 才下载成功。。。

编译

使用命令 emcc 可以把c++ 编译成js,如果你一上来就敲emcc 那么不好意思 是不存在的 先要运行下面的命令设置好当前进程的环境才能编译

C:\inno\libraries\emsdk\emsdk activate latest

C:\inno\libraries\emsdk\emsdk_env.bat


然后可以使用emcc了,说白了 每次打开cmd窗口 先要调用下上面那个命令

编译很简单 

emcc main.cpp -o main.js

main.cpp

void main()

{

print("Hello World");

}

输出的main.js 内容很多,内嵌了一些基础实现,但我搜索不到“Hello World”的字样,虽然没弄明白原理但觉得可以用来加密代码

折腾了很久 最后我选用的编译选项是

emcc --bind demo.cpp -o demo.js -s WASM=0 -O3 --memory-init-file 0 --pre-js pre.js --post-js post.js

我觉得这才是实战所需要的,实在看不上-s EXPORTED_FUNCTIONS="['_main', '_myfunc']" 然后用module.ccall。。。

--bind 是指可以EMSCRIPTEN_BINDINGS来声明需要导出的类以及单个函数

-s WASM=0 不要生成web assembly 即.wasm文件,因为这里暂时用不上

-O3 优化级别是3的 默认是不会优化的

--memory-init-file 这个完全是为了填-O3的坑,因为打开优化后生成文件除了.js还有一个 .js.mem, js加载进来之后还要去加载.js.mem文件之后才能用导出的函数 这里是异步的,需要注册Module.onRuntimeInitialized这个回调才能继续,那么这个参数是不要 生成mem文件,舍弃这些麻烦。

--pre-js pre.js  和 --post-js post.js 是加在生成的js首尾的js,本来是用来做匿名的,但看生成的话 有点搞笑。。。

可以欣赏这里所有源码

变量传递

https://kripken.github.io/emscripten-site/docs/api_reference/emscripten.h.html#inline-assembly-javascript 这里讲了使用EM_XX 怎么在c++里内联js代码,然后怎么交互,c++怎么传值(数字和指针)给js,js怎么返回值(数字和指针)给c++ 写的很详细 足够了

在EMSCRIPTEN_BINDINGS中传递Uint8Array

cpp

#include <string>

#include <malloc.h>

#include <functional>

#include <emscripten/bind.h>

typedef  unsigned char uchar;

class MyClass

{


public:

    MyClass()

    {

        data = new uchar[100];

        size = 100;

    }

    emscripten::val getData () const

    {

        return emscripten::val(emscripten::memory_view<uchar>(size,data));

    }

private:

    int size;

    uchar* data;

};

EMSCRIPTEN_BINDINGS(my_class) {

  emscripten::class_<MyClass>("MyClass")

    .constructor()

    .property("data", &MyClass::getData)

    ;

}

js

var my = new inno.MyClass();

var ctx = cin.getContext('2d');

my.data.set(ctx.getImageData(0, 0, w, h).data);

var imgData = new ImageData(new Uint8ClampedArray(my.data), w, h);

ctx.putImageData(imgData, 0, 0);

另一种方式

cpp

class MyClass{

public:

    MyClass(int w, int h){

    }

    void setData(intptr_t frame4b_ptr)

    {

    //frame4b_ptr[0]

    }

};

EMSCRIPTEN_BINDINGS(my_class) {

  emscripten::class_<MyClass>("MyClass")

    .constructor()

  .function("update", &MyClass::updasetDatate, emscripten::allow_raw_pointers())

    ;

}

JS

var data = this.ctx.getImageData(0, 0, w, h);

var bytes = arrayToHeap(data.data);

my.setData(bytes.byteOffset);

data.data.set(bytes);

this.ctx.putImageData(data, 0, 0)

;

function freeArray(heapBytes) {

    Module._free(heapBytes.byteOffset);

}

function arrayToHeap(typedArray) {

    var numBytes = typedArray.length * typedArray.BYTES_PER_ELEMENT;

    var ptr = Module._malloc(numBytes);

    heapBytes = Module.HEAPU8.subarray(ptr, ptr + numBytes);

    heapBytes.set(typedArray);

    return heapBytes;

}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容

  • 大学好友住院已经有快两周的时间了,本来以为已经恢复,今早打探才得知,还在恢复中,并未出院,我决定马上去探望一下,不...
    LRIGEHT反转小姐阅读 252评论 0 0
  • 從無到有,這個過程是种怎樣的體會? 而又有多少人在從無到有的過程中敢於去追求呢?如果是原來的我,除了抱...
    落子无悔ss阅读 163评论 0 0