Emscripten——js 调用 C++ 接口

Emscripten 提供了许多方法来在 JavaScript 和编译后的 C 或 c++ 之间连接和交互,我们先来看看 js 调用 WASM 的情况。 一、使用 ccall 或 cwrap callall() 调用带有指定参数的编译过的 C 函数 并返回结果,而 cwrap() 封装了编译过的 C 函数并返回一个可以正常调用的 JavaScript 函数。因此,如果计划多次调用一个编译后的函数,cwrap() 会更有用。 例如下面的 C main.cpp 文件: #include <math.h> extern "C" { int int_sqrt(int x) { return sqrt(x); } } 使用下面的命令进行编译: emcc main.cpp -o function.html -s EXPORTED_FUNCTIONS=_int_sqrt -s EXPORTED_RUNTIME_METHODS=ccall,cwrap EXPORTED_FUNCTIONS 告诉编译器哪些函数我们想要导出(不指定的函数会被删掉),EXPORTED_RUNTIME_METHODS 告诉编译器我们需要用到的运行时方法 ccall 和 cwrap,否则这些方法也会被优化掉 编译后就可以在 js 中通过 cwrap 使用了: int_sqrt = Module.cwrap('int_sqrt', 'number', ['number']) int_sqrt(12) // return 3 int_sqrt(28) // return 5 第一个参数是被 wrap 的 C 函数的名字(没有下划线),第二个参数是函数返回值在类型(如果没有返回值,使用 JavaScript 的 null 类型),第三个参数是一个参数数组(如果没有参数,可以省略)。...

March 25, 2022 · 2 min · Rick Cui

Emscripten——使用 CMake 构建并用 Make 编译

使用 CMake 构建 在源文件目录添加 CMakeList.txt 文件 # 设置CMake版本最低要求 cmake_minimum_required(VERSION 3.10)# 设置项目名称和版本 set(MyTarget hello)project(${MyTarget} VERSION 1.0)# 指定 C++ 标准 set(CMAKE_CXX_STANDARD 11)set(CMAKE_CXX_STANDARD_REQUIRED True)# 编译生成.html文件 set(CMAKE_EXECUTABLE_SUFFIX ".html")# 添加源码文件和生成的目标文件的名称 # file(GLOB_RECURSE SRC_MAIN ./*.cpp) aux_source_directory(./ SRC_MAIN)aux_source_directory(./thirdParty/ SRC_MAIN)add_executable(${MyTarget} ${SRC_MAIN})# add_executable(${MyTarget} main.cpp) # 设置Emscripten的编译链接参数 set_target_properties(${MyTarget} PROPERTIES LINK_FLAGS " \ -s EXIT_RUNTIME=0 \ -gsource-map \ -s EXPORTED_FUNCTIONS=_main,_sayHello1,_jsonParse,_jsonParse1 \ -s EXPORTED_RUNTIME_METHODS=ccall,cwrap,addFunction \ -s NO_DISABLE_EXCEPTION_CATCHING \ ")# 添加第三方库路径 # target_link_directories(${MyTarget} # PUBLIC "${PROJECT_BINARY_DIR}" # ) # 将第三方库与主程序进行链接 # set(LIBS cjson) # target_link_libraries(sample ${LIBS}) # 添加头文件查找路径 target_include_directories(${MyTarget} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}" ) 创建 build 文件夹,并在 build 文件夹内执行命令 emcmake cmake ....

March 24, 2022 · 1 min · Rick Cui

Emscripten——C++ 函数导出

导出 C++ 函数到 js 有多种方式: 方式一:在编译的时候指定 在编译命令中添加 -sEXPORTED_FUNCTIONS 参数,例如:-s EXPORTED_FUNCTIONS=_myFunction,_sayHello1 方式二:修改 C++ 函数 在 C++ 代码中需要导出的函数声明前添加 EMSCRIPTEN_KEEPALIVE 宏定义 #include <emscripten.h> extern "C" int EMSCRIPTEN_KEEPALIVE myFunction(int argc, char ** argv) { printf("我的函数已被调用\n"); return 0; } #ifdef __cplusplus extern "C" { #endif int EMSCRIPTEN_KEEPALIVE sayHello(){ cout << "hello from sayHello!" << endl; return 0; } int sayHello1() { Person p; cout << p.printInfo() << endl; return 0; } #ifdef __cplusplus } #endif 方式三:WebIDL Binder...

March 24, 2022 · 1 min · Rick Cui

Emscripten——Hello World

编译 新建 main.cpp 文件 #include <iostream>using namespace std; int main(){ cout << "hello world!" << endl; return 0; } 使用 emcc 或 em++ 编译 C++ 文件 执行命令 em++ main.cpp,会在同级目录下生成 a.out.js 和 a.out.wasm 两个文件。 使用 node 测试 测试命令 node a.out.js,会在控制台输出 cout 的内容 使用 html 页面 测试 执行命令 em++ main.cpp -o hello.html,会在同级目录下生成三个文件: hello.html:测试网页 hello.js:相关的胶水代码,包括加载 WASM 文件并执行调用等相关逻辑 hello.wasm:编译得到的核心 WebAssembly执行文件 在本地启动一个静态网站服务器,就可以在浏览器中访问生成的网页了 编译带有 调试 信息的测试页面...

March 24, 2022 · 1 min · Rick Cui

Emscripten——安装

启用 Linux 环境 这里使用的是 WSL(Windows Subsystem Linux)环境,环境配置参考这里 Linux 安装 Emscripten Download and install 安装 python3 sudo apt install python3 安装 git sudo apt install git 创建目录并 clone emsdk sudo git clone https://github.com/emscripten-core/emsdk.git 更新 emsdk 并激活 cd emsdk git pull # Download and install the latest SDK tools. ./emsdk install latest # Make the "latest" SDK "active" for the current user. (writes .emscripten file) ....

March 24, 2022 · 1 min · Rick Cui