Emscripten實現把C/C++文件轉成wasm,wast(wasm的可讀形式),llvm字節碼(bc格式),ll格式(llvm字節碼的可讀形式)並執行wasm

《一》˙轉換javascript

Emscripten實現把C/C++文件轉成wasm,wast(wasm的可讀形式),llvm字節碼(bc格式),ll格式(llvm字節碼的可讀形式)的步驟:html

最新版本的Emscripten(1.38.12)已經能實現把c/c++轉成wasm文件,例子;java

(1)源文件:extern.cc  若是不加extern 「c」{}則轉出的wasm文件對應的wast文件只有module這個詞。node

extern "C" {c++

int add(int x, int y) {web

  int a=333;npm

  return x + y+ a;瀏覽器

}服務器

int min(int x, int y) {app

  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 <stdio.h>

#include <emscripten.h>

 

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 <emscripten.h>

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

 <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">

<body>

<h1>Test File</h1>

 

<script type="text/javascript">

    var Module = {

      onRuntimeInitialized: function() {

        var a=Module._add(1,2); 

        document.write("result == " + a);

      }

    };

  </script>

<script type="text/javascript" src="extern.js"></script>

</body>

 

 在當前目錄使用serve運行 serve -l 8000 (若是沒有serve,則執行npm install -g serve)

 執行:在瀏覽器地址打開 localhost:8000/test

相關文章
相關標籤/搜索