Emscripten实现把C/C++文件转成wasm,wast(wasm的可读形式),llvm字节码(bc格式),ll格式(llvm字节码的可读形式)并执行wasm | 您所在的位置:网站首页 › wast › Emscripten实现把C/C++文件转成wasm,wast(wasm的可读形式),llvm字节码(bc格式),ll格式(llvm字节码的可读形式)并执行wasm |
《一》˙转换 Emscripten实现把C/C++文件转成wasm,wast(wasm的可读形式),llvm字节码(bc格式),ll格式(llvm字节码的可读形式)的步骤: 最新版本的Emscripten(1.38.12)已经能实现把c/c++转成wasm文件,例子; (1)源文件:extern.cc 如果不加extern “c”{}则转出的wasm文件对应的wast文件只有module这个词。 extern "C" { int add(int x, int y) { int a=333; return x + y+ a; } int min(int x, int y) { return x - y; } } (2)转成wasm命令: emcc extern.cc -o extern.js -s EXPORTED_FUNCTIONS='["_add","_min"]' -O3 注意:这里EXPORTED_FUNCTIONS指的是导出的函数,需要和源文件里的函数名是相对应的,-O3是编译优化等级,只有这个等级生成的wasm文件才会很小(几十字节),不加该优化选项,生成的wasm将会有几十KB。生成的时候会临时产生*.asm.js,等生成完后,会自动删掉。 执行完将会生成 extern.js和extern.wasm两个文件。
(3)转成wast可读文件: wasm2wat extern.wasm -o extern.wast wast文件内容: (module (type (;0;) (func (param i32 i32) (result i32))) (func (;0;) (type 0) (param i32 i32) (result i32) get_local 0 get_local 1 i32.sub) (func (;1;) (type 0) (param i32 i32) (result i32) get_local 0 i32.const 333 i32.add get_local 1 i32.add) (export "_add" (func 1)) (export "_min" (func 0)))
(4)转成llvm字节码 bc格式: emcc extern.cc -o extern.bc -s EXPORTED_FUNCTIONS='["_add","_min"]' -O3
(5)使用llvm-dis把llvm字节码转成可读格式: llvm-dis extern.bc 执行上述命令将生成extern.ll文件。 extern.ll 文件内容: ; ModuleID = 'extern.bc' source_filename = "extern.cc" target datalayout = "e-p:32:32-i64:64-v128:32:128-n32-S128" target triple = "asmjs-unknown-emscripten"
; Function Attrs: norecurse nounwind readnone define i32 @add(i32, i32) local_unnamed_addr #0 { %3 = add i32 %0, 333 %4 = add i32 %3, %1 ret i32 %4 }
; Function Attrs: norecurse nounwind readnone define i32 @min(i32, i32) local_unnamed_addr #0 { %3 = sub nsw i32 %0, %1 ret i32 %3 }
attributes #0 = { norecurse nounwind readnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
!llvm.module.flags = !{!0} !llvm.ident = !{!1}
!0 = !{i32 1, !"wchar_size", i32 4} !1 = !{!"clang version 6.0.1 (emscripten 1.38.12 : 1.38.12)"} 最终生成的文件列表如下图:
《二》执行 Emscripten(1.38.12)执行把c/c++转成wasm文件的方法: 方法一:用node执行 源文件:extern-node.cc #include #include
extern "C"{ void sayHi() { printf("Hi!\n"); }
int daysInWeek() { return 7; } } 编译命令: emcc -s EXPORTED_FUNCTIONS="['_sayHi', '_daysInWeek']" extern-node.cc -o extern-node.js 编写node-test.js var em_module = require('./extern-node.js');
em_module._sayHi(); em_module.ccall("sayHi"); console.log(em_module._daysInWeek()); 执行: Node node-test.js
方法二:用web服务器执行 源文件:extern.cc #include extern "C"{ int gol=1111; int add(int x, int y) { int a= 333; //printf("hello world! %d\n",a); return x + y+ a+gol; }
int min(int x, int y) { return x - y; } } 编译命令: emcc extern.cc -s EXPORTED_FUNCTIONS="['_add']" -o extern.js 编写test.html
Test File
var Module = { onRuntimeInitialized: function() { var a=Module._add(1,2); document.write("result == " + a); } };
在当前目录使用serve运行 serve -l 8000 (如果没有serve,则执行npm install -g serve) 执行:在浏览器地址打开 localhost:8000/test |
CopyRight 2018-2019 实验室设备网 版权所有 |