使用Emscripten 將c/c++編譯成js

背景

最近搞open cv識別物體的項目家卖,因為客戶需求纠炮,最終決定使用js來實現(xiàn)嘉裤。

捕獲攝像頭 是通過navigator.mediaDevices槐瑞,前提是 ios 需要11以上必須是https犹芹, android到還好崎页。

識別物體通過opencv js 。

雖然坎坎坷坷 但是第一版還是上線了 除了https和默認顯示后置攝像頭(Android的枚舉攝像頭 根據(jù)label判斷是否是后置的腰埂,IOS 中的facingMode:{exact:"environment"} 是有效的)飒焦,其它還算順利。

然后 然后 opencv js 10M 這個大小比較要命屿笼。牺荠。。

opencv是通過Emscripten 將c編譯成js的?

所以打算ctrl+c驴一, ctrl+v 精減下源碼志电,再編譯下,將js文件減少到500kb之內(nèi)是沒有問題的蛔趴。

安裝

安裝 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 那么不好意思 是不存在的 先要運行下面的命令設(shè)置好當前進程的環(huán)境才能編譯

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

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


然后可以使用emcc了魁亦,說白了 每次打開cmd窗口 先要調(diào)用下上面那個命令

編譯很簡單?

emcc main.cpp -o main.js

main.cpp

void main()

{

print("Hello World");

}

輸出的main.js 內(nèi)容很多,內(nèi)嵌了一些基礎(chǔ)實現(xiàn)羔挡,但我搜索不到“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

我覺得這才是實戰(zhàn)所需要的,實在看不上-s EXPORTED_FUNCTIONS="['_main', '_myfunc']" 然后用module.ccall绞灼。利术。。

--bind 是指可以EMSCRIPTEN_BINDINGS來聲明需要導(dǎo)出的類以及單個函數(shù)

-s WASM=0 不要生成web assembly 即.wasm文件低矮,因為這里暫時用不上

-O3 優(yōu)化級別是3的 默認是不會優(yōu)化的

--memory-init-file 這個完全是為了填-O3的坑印叁,因為打開優(yōu)化后生成文件除了.js還有一個 .js.mem, js加載進來之后還要去加載.js.mem文件之后才能用導(dǎo)出的函數(shù) 這里是異步的,需要注冊Module.onRuntimeInitialized這個回調(diào)才能繼續(xù)轮蜕,那么這個參數(shù)是不要 生成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++里內(nèi)聯(lián)js代碼葱蝗,然后怎么交互,c++怎么傳值(數(shù)字和指針)給js韩玩,js怎么返回值(數(shù)字和指針)給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;

}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市陆馁,隨后出現(xiàn)的幾起案子找颓,更是在濱河造成了極大的恐慌,老刑警劉巖叮贩,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件击狮,死亡現(xiàn)場離奇詭異,居然都是意外死亡益老,警方通過查閱死者的電腦和手機彪蓬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來捺萌,“玉大人档冬,你說我怎么就攤上這事√掖浚” “怎么了酷誓?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長态坦。 經(jīng)常有香客問我盐数,道長,這世上最難降的妖魔是什么伞梯? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任玫氢,我火速辦了婚禮,結(jié)果婚禮上谜诫,老公的妹妹穿的比我還像新娘漾峡。我一直安慰自己,他們只是感情好喻旷,可當我...
    茶點故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布灰殴。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪牺陶。 梳的紋絲不亂的頭發(fā)上伟阔,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天,我揣著相機與錄音掰伸,去河邊找鬼皱炉。 笑死,一個胖子當著我的面吹牛狮鸭,可吹牛的內(nèi)容都是我干的合搅。 我是一名探鬼主播,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼歧蕉,長吁一口氣:“原來是場噩夢啊……” “哼灾部!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起惯退,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤赌髓,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后催跪,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體锁蠕,經(jīng)...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年懊蒸,在試婚紗的時候發(fā)現(xiàn)自己被綠了荣倾。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,566評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡骑丸,死狀恐怖舌仍,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情通危,我是刑警寧澤抡笼,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站黄鳍,受9級特大地震影響推姻,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜框沟,卻給世界環(huán)境...
    茶點故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一藏古、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧忍燥,春花似錦拧晕、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春靡馁,著一層夾襖步出監(jiān)牢的瞬間欲鹏,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工臭墨, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留赔嚎,地道東北人。 一個月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓胧弛,卻偏偏與公主長得像尤误,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子结缚,可洞房花燭夜當晚...
    茶點故事閱讀 43,440評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 大學好友住院已經(jīng)有快兩周的時間了红竭,本來以為已經(jīng)恢復(fù)尤勋,今早打探才得知,還在恢復(fù)中德崭,并未出院斥黑,我決定馬上去探望一下揖盘,不...
    LRIGEHT反轉(zhuǎn)小姐閱讀 256評論 0 0
  • 從無到有眉厨,這個過程是種怎樣的體會? 而又有多少人在從無到有的過程中敢於去追求呢兽狭?如果是原來的我憾股,除了抱...
    落子無悔ss閱讀 163評論 0 0