首页 > 编程语言 >WebAssembly C++开发环境搭建

WebAssembly C++开发环境搭建

时间:2023-10-11 15:55:45浏览次数:55  
标签:WebAssembly WORKPATH C++ js wasm var FLAGS 搭建

WebAssembly 开发环境搭建

简介

WebAssembly 是一种新的编码方式,可以在现代的网络浏览器中运行 - 它是一种低级的类汇编语言,具有紧凑的二进制格式,可以接近原生的性能运行,并为诸如C/C++等语言提供一个编译目标,以便它们可以在 Web 上运行。它也被设计为可以与 JavaScript 共存,允许两者一起工作。

简而言之,对于网络平台而言,WebAssembly 具有巨大的意义——它提供了一条途径,以使得以各种语言编写的代码都可以以接近原生的速度在 Web 中运行。在这种情况下,以前无法以此方式运行的客户端软件都将可以运行在 Web 中。

WebAssembly 被设计为可以和 JavaScript 一起协同工作——通过使用 WebAssembly 的 JavaScript API,你可以把 WebAssembly 模块加载到一个 JavaScript 应用中并且在两者之间共享功能。这允许你在同一个应用中利用 WebAssembly 的性能和威力以及 JavaScript 的表达力和灵活性,即使你可能并不知道如何编写 WebAssembly 代码。

本文展示了将 FFmpeg 应用到 WebAssembly 的例子。

编译环境

https://hub.docker.com/r/emscripten/emsdk/tags
拉取远程镜像

docker pull emscripten/emsdk:2.0.24

启动容器

映射自己的目录

docker run -d -it --name mediawasm -v d:/.../wasmff:/code  emscripten/emsdk:2.0.24 /bin/bash

编译

编译脚本

#!/bin/bash

#set -eo pipefail

WORKPATH=$(cd $(dirname $0); pwd)

DEMO_PATH=$WORKPATH/demo

echo "WORKPATH"=$WORKPATH

rm -rf ${WORKPATH}/demo/mp4encoder.js ${WORKPATH}/demo/mp4encoder.wasm

FFMPEG_ST=yes

EMSDK=/emsdk

THIRD_DIR=${WORKPATH}/lib/third/build

# 生成调试文件
DEBUG="-g -fno-inline -gseparate-dwarf=/code/demo/temp.debug.wasm -s SEPARATE_DWARF_URL=http://localhost:5000/temp.debug.wasm"

#--closure 压缩胶水代码,有可能会造成变量重复定义。生产发布可设为1
OPTIM_FLAGS="-O1 $DEBUG --closure 0"

if [[ "$FFMPEG_ST" != "yes" ]]; then
  EXTRA_FLAGS=(
    -pthread
    -s USE_PTHREADS=1                             # enable pthreads support
    -s PROXY_TO_PTHREAD=1                         # detach main() from browser/UI main thread
    -o ${DEMO_PATH}/mp4encoder.js
  )
else
  EXTRA_FLAGS=(
    -o ${DEMO_PATH}/mp4encoder.js
  )
fi

FLAGS=(
  -I$WORKPATH/lib/ffmpeg-emcc/include -L$WORKPATH/lib/ffmpeg-emcc/lib -I$THIRD_DIR/include -L$THIRD_DIR/lib
  -Wno-deprecated-declarations -Wno-pointer-sign -Wno-implicit-int-float-conversion -Wno-switch -Wno-parentheses -Qunused-arguments
  -lavdevice -lavfilter -lavformat -lavcodec -lswresample -lswscale -lavutil -lpostproc 
  -lm -lharfbuzz -lfribidi -lass -lx264 -lx265 -lvpx -lwavpack -lmp3lame -lfdk-aac -lvorbis -lvorbisenc -lvorbisfile -logg -ltheora -ltheoraenc -ltheoradec -lz -lfreetype -lopus -lwebp
  $DEMO_PATH/encode_v.c
  
  -s FORCE_FILESYSTEM=1
  -s WASM=1
  -s USE_SDL=2                                  # use SDL2
  -s INVOKE_RUN=0                               # not to run the main() in the beginning
  -s EXIT_RUNTIME=1                             # exit runtime after execution
  -s MODULARIZE=1                               # 延迟加载 use modularized version to be more flexible
  -s EXPORT_NAME="createMP4Encoder"             # assign export name for browser
  -s EXPORTED_FUNCTIONS="[_main,_malloc,_free]" # export main and proxy_main funcs
  -s EXPORTED_RUNTIME_METHODS="[FS, cwrap, ccall, setValue, writeAsciiToMemory]"   # export preamble funcs
  -s INITIAL_MEMORY=134217728                   # 64 KB * 1024 * 16 * 2047 = 2146435072 bytes ~= 2 GB
  -s ALLOW_MEMORY_GROWTH=1                      # 允许动态扩展内存
  --pre-js $WORKPATH/pre.js
  --post-js $WORKPATH/post.js
  $OPTIM_FLAGS
  ${EXTRA_FLAGS[@]}
)
echo "FFMPEG_EM_FLAGS=${FLAGS[@]}"

emcc "${FLAGS[@]}"

./build-demo.sh

会在项目目录下生成 mp4encoder.jsmp4encoder.wasm 其中js文件文件为胶水代码,使得C++接口能在浏览器js中调用。实际的C++逻辑存放于wasm文件中。

在容器外的项目目录下, 启动web静态服务器查看效果

调试

介绍
https://developer.chrome.com/blog/wasm-debugging-2020/
下载安装插件
https://goo.gle/wasm-debugging-extension

1、打开开发者工具,设置(F1) -> 实验 -> 勾选 WebAssembly Debug

2、因为项目在Docker下编译,需要把Docker路径映射到本地磁盘


3、打开开发者工具 -> 源代码 -> 左侧file://下即可找到源代码 -> 设置断点 -> 右侧监视添加变量

参数传递

简单参数传递

  //把js string 转成 utf8 array
  var getCStringPtr = function (jstr) {
    var lengthBytes = lengthBytesUTF8(jstr) + 1;
    var p = MP4Encoder._malloc(lengthBytes);
    stringToUTF8(jstr, p, lengthBytes);
    return p;
  }
  //allocateUTF8功能相同

  //值类型可以直接传递,string必须先转array
  var strPtr = getCStringPtr("/tmp/demo2.mp4");
  var ret = MP4Encoder._createH264(strPtr, 1920, 1080, 25);

大块内存拷贝

    //js 数组内存
    let fileBuffer = new Uint8Array(imagedata.data.buffer);
    //wasm 数组内存
    let bufferPtr = MP4Encoder._malloc(fileBuffer.length);
    //js -> wasm
    MP4Encoder.HEAP8.set(fileBuffer, bufferPtr);
    var ret = MP4Encoder._addFrame(bufferPtr);

_malloc_free 这些系统方法是模块默认导出的。如果想查看其他方法是否可用,可以控制台打印MP4Encoder模块看其挂载的方法

文件读写

<input type="file" value="选择文件" onchange="inputJsFile(event)"></input>
  var inputJsFile = function (event) {
    let file = event.target.files[0];

    file.arrayBuffer().then(t=>{
      console.log(t)
      //创建文件夹
      FS.mkdir('/working');
      //写入二进制数据到wasm虚拟目录
      FS.writeFile('/working/input.txt', new Uint8Array(t), { flags:'w+' });
      //查看写入成功
      console.log(FS.stat('/working/input.txt'))
      //从wasm读取到js
      var buff = FS.readFile('/working/input.txt', { encoding: 'binary' });
      console.log(buff)
      var pStr = getCStringPtr("/working/input.txt");
      var ret = MP4Encoder._openTestFile(pStr);
    });
  }

项目地址
https://github.com/gaobowen/wasmff

扩展阅读
https://developer.mozilla.org/zh-CN/docs/WebAssembly
https://developer.mozilla.org/zh-CN/docs/Web/API/IndexedDB_API
https://emscripten.org/docs/api_reference/index.html

标签:WebAssembly,WORKPATH,C++,js,wasm,var,FLAGS,搭建
From: https://www.cnblogs.com/gaobw/p/17757325.html

相关文章

  • c++编译报错解决办法
    所有的警告都被当作是错误在全局域:cc1plus:错误:unrecognizedcommandlineoption‘-Wno-unknown-warning’[-Werror]cc1plus:所有的警告都被当作是错误解决办法:去除CMakeLists.txt中的-Werror......
  • 基于 ACK Fluid 的混合云优化数据访问(二):搭建弹性计算实例与第三方存储的桥梁
    作者:车漾前文回顾:本系列将介绍如何基于ACKFluid支持和优化混合云的数据访问场景,相关文章请参考:基于ACKFluid的混合云优化数据访问(一):场景与架构在前文《场景与架构》中,重点介绍ACKFluid支持混合云数据访问适用的不同应用场景和架构实现。在本文中会重点介绍如何通过ACKFl......
  • C++ - 文件读写
    5文件操作 程序运行时产生的数据都属于临时数据,程序一旦运行结束都会被释放通过文件可以将数据持久化C++中对文件操作需要包含头文件==<fstream>== 文件类型分为两种:文本文件-文件以文本的ASCII码形式存储在计算机中二进制文件-文件以文本的二进制形式存储......
  • C++ - 模板
     本阶段主要针对C++泛型编程和STL技术做详细讲解,探讨C++更深层的使用1模板1.1模板的概念模板就是建立通用的模具,大大提高复用性 模板的特点:模板不可以直接使用,它只是一个框架模板的通用并不是万能的 1.2函数模板 C++另一种编程思想称为==泛型编程......
  • C++ - STL算法
    5STL-常用算法 概述:算法主要是由头文件<algorithm><functional><numeric>组成。 <algorithm>是所有STL头文件中最大的一个,范围涉及到比较、交换、查找、遍历操作、复制、修改等等<numeric>体积很小,只包括几个在序列上面进行简单数学运算的模板函数<funct......
  • 基于亚马逊云科技高可靠性的EC2云服务器,搭建功能无限制的私人网盘
    网盘是一种在线存储服务,提供文件存储,访问,备份,贡献等功能,是我们日常中不可或缺的一种服务。很多互联网公司都为个人和企业提供免费的网盘服务。但这些免费服务都有一些限制,比如限制下载速度,限制文件大小,不能多人同时管理,不能实现一些定制化功能。如果想取消这些限制,就要付费。现在为......
  • C++ - 数组
    5数组5.1概述所谓数组,就是一个集合,里面存放了相同类型的数据元素特点1:数组中的每个==数据元素都是相同的数据类型==特点2:数组是由==连续的内存==位置组成的 5.2一维数组一维数组 5.2.1一维数组定义方式一维数组定义的三种方式:数据类型数组名[数组长度];......
  • C++ - 函数
    6函数6.1概述作用:将一段经常使用的代码封装起来,减少重复代码一个较大的程序,一般分为若干个程序块,每个模块实现特定的功能。6.2函数的定义函数的定义一般主要有5个步骤:1、返回值类型2、函数名3、参数表列4、函数体语句5、return表达式语法:返回值类型函数名(参数......
  • C++ - 指针
    7指针7.1指针的基本概念指针的作用:可以通过指针间接访问内存 内存编号是从0开始记录的,一般用十六进制数字表示可以利用指针变量保存地址 7.2指针变量的定义和使用指针变量定义语法:数据类型*变量名;示例:intmain(){ //1、指针的定义 inta=10;//定......
  • C++ - 结构体
    8结构体8.1结构体基本概念结构体属于用户==自定义的数据类型==,允许用户存储不同的数据类型 8.2结构体定义和使用语法:struct结构体名{结构体成员列表};通过结构体创建变量的方式有三种:struct结构体名变量名struct结构体名变量名={成员1值,成员2值...}......