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

C++11 左值、右值和移动语义

一、结论 C 中将数据类型分为左值和右值,在 C++11 中又将右值概念更为细致的分为将亡值(xvalue)和纯右值(prvalue)。 将亡值是 C++11 新增的跟右值引用相关的表达式,通常是将要被移动的对象(移为他用),比如返回右值引用 T&& 的函数返回值、std::move 的返回值。 从性能上讲,左右值引用没有区别,传参使用左右值引用都可以避免拷贝。 右值引用可以直接指向右值,也可以通过 std::move 指向左值;而左值引用只能指向左值(const左值引用也能指向右值)。 作为函数形参时,右值引用更灵活。虽然 const 左值引用也可以做到左右值都接受,但它无法修改,有一定局限性。 可移动对象在需要拷贝且被拷贝者之后不再被需要的场景,建议使用 std::move 触发移动语义,提升性能。 我们可以在自己的类中实现移动语义,避免深拷贝,充分利用右值引用和 std::move 的语言特性。 std::move 本身只做类型转换,对性能无影响。 std::forward 同样也是做类型转换且更强大,move 只能转出来右值,forward 既可以转成右值,又可以转成左值。 函数最好不要返回函数体内局部变量的左值引用或右值引用。 二、注意事项 左值引用是具名变量值的别名 右值引用是不具名(匿名)变量的别名 引用是变量的别名,由于右值没有地址,没法被修改,所以左值引用无法指向右值,但是,const左值引用是可以指向右值的 const int &ref_a = 5; int a = 5; int &ref_a = a; // 左值引用指向左值,编译通过 int &ref_a = 5; // 左值引用指向了右值,会编译失败 右值引用的标志是 &&,顾名思义,右值引用专门为右值而生,可以指向右值,不能指向左值 int&& ref_a_right = 5; // ok int a = 5; int&& ref_a_left = a; // 编译不过,右值引用不可以指向左值 ref_a_right = 6; // 右值引用的用途:可以修改右值 事实上 std::move 移动不了什么,唯一的功能是把左值强制转化为右值,让右值引用可以指向左值。其实现等同于一个类型转换:static_cast<T&&>(lvalue)。 所以,单纯的 std::move(xxx) 不会有性能提升,从这个角度来讲,右值引用和左值引用的功能相似,都是原始变量的别名,至于移动后原始变量是否可用,取决于被移动的数据类型对于移动语义的具体实现。...

February 23, 2022 · 4 min · Rick Cui