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.jsextern.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-disllvm字节码转成可读格式:

 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

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
首先,确保你的项目已经正确地链接了 Emscripten SDK。接下来,在 CMakeLists.txt 中添加以下内容: ```cmake cmake_minimum_required(VERSION 3.0) project(your_project) # 设置编译选项 set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) # 添加 Emscripten 编译器 SET(CMAKE_C_COMPILER "emcc") SET(CMAKE_CXX_COMPILER "em++") # 添加 Emscripten 编译选项 SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s WASM=1 -s USE_SDL=2 -s USE_WEBGL2=1 -s FULL_ES3=1 -s USE_GLFW=3") # 添加源代码 add_executable(your_project main.cpp) # 导出 C 函数为 JavaScript 模块 set_target_properties(your_project PROPERTIES LINK_FLAGS "-s EXPORTED_FUNCTIONS='[\"_your_c_function\"]' -s EXTRA_EXPORTED_RUNTIME_METHODS='[\"ccall\", \"cwrap\"]'") # 指定输出文件名 set_target_properties(your_project PROPERTIES OUTPUT_NAME "your_project") # 指定输出文件类型为 JavaScript 模块 set_target_properties(your_project PROPERTIES SUFFIX ".js") # 拷贝输出文件到指定目录 add_custom_command(TARGET your_project POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:your_project> ${CMAKE_CURRENT_SOURCE_DIR}/output/) ``` 以上代码做了以下几件事: 1. 设置编译选项,包括编译标准、编译器等等。 2. 添加 Emscripten 编译器和编译选项。 3. 添加源代码。 4. 导出 C 函数为 JavaScript 模块,这里的 `_your_c_function` 是你需要导出的函数名。 5. 指定输出文件名为 `your_project.js`。 6. 拷贝输出文件到指定目录。 最后,你可以通过以下命令来生成 WebAssembly 项目: ```bash mkdir build && cd build cmake .. make ``` 如果一切顺利,你将得到 `your_project.js` 和 `your_project.wasm` 两个文件,其中前者是 JavaScript 模块,后者是 WebAssembly 模块。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值