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 C++开发环境搭建的更多相关文章

  1. python开发环境搭建

    虽然网上有很多python开发环境搭建的文章,不过重复造轮子还是要的,记录一下过程,方便自己以后配置,也方便正在学习中的同事配置他们的环境. 1.准备好安装包 1)上python官网下载python运 ...

  2. IntelliJ IDEA安装及jsp开发环境搭建

    一.前言 现在.net国内市场不怎么好,公司整个.net组技术转型,就个人来说还是更喜欢.net,毕竟不是什么公司都像微软一样财大气粗开发出VS这样的宇宙级IDE供开发者使用,双击sln即可打开项目, ...

  3. Qt for Android开发环境搭建及测试过程记录

    最近学习了Qt的QML编程技术,感觉相较于以前的QtGUI来说更方便一些,使用QML可以将界面与业务逻辑解耦,便于开发. QML支持跨平台,包括支持Android平台,因此可以使用Qt的QML进行An ...

  4. node.js之开发环境搭建

    一.安装linux系统 (已安装linux可跳此步骤) 虚拟机推荐选择:VirtualBox 或者 Vmware (专业版永久激活码:5A02H-AU243-TZJ49-GTC7K-3C61N) 我这 ...

  5. TODO:小程序开发环境搭建

    TODO:小程序开发环境搭建 1.第一步当然是要先注册小程序了 2.登录到小程序 a)完善小程序信息,如名称,图标,描述 3.绑定开发者 4.获取AppID,并设置服务器信息 5.下载并安装开发者工具 ...

  6. Eclipse中Python开发环境搭建

    Eclipse中Python开发环境搭建  目 录  1.背景介绍 2.Python安装 3.插件PyDev安装 4.测试Demo演示 一.背景介绍 Eclipse是一款基于Java的可扩展开发平台. ...

  7. Windows 10 IoT Serials 1 - 针对Minnow Board MAX的Windows 10 IoT开发环境搭建

    目前,微软针对Windows IoT计划支持的硬件包括树莓派2,Minnow Board MAX 和Galileo (Gen 1和Gen 2).其中,Galileo (Gen 1和Gen 2)运行的是 ...

  8. Eclipse swt开发环境搭建

    原料: eclipse swt.下载链接为: Eclipse 4.6.2 Release Build: 4.6.2 配置说明: Developing SWT applications using Ec ...

  9. Ionic- Android 开发环境搭建

    Ionic- Android 开发环境搭建 为时一周的IONIC ADNROID 环境终于在各种处理错误中搭建成功,以下记录下搭建过程中遇到的各种情况的处理办法. 一 首先,当然是enviroment ...

  10. visual studio 2015 + Cordova 开发环境搭建

    简单的写一些,备忘,太折腾了,特别是通过代理上网的我们国内的开发者 1.当然是安装Visual Studio 2015,别忘了选择Tools For Apache Cordova. 对于通过Proxy ...

随机推荐

  1. 【Mybatis】Bonus02 补充

    关于主键生成问题 Mybatis的主键生成是基于JDBC的使用主键[getGeneratedKeys()]方法 也就是说,必须要JDBC驱动的支持才行 @Test public void junitT ...

  2. 【DataBase】排课设计思路

    想设计一个排课系统,看了网上文库的表结构设计弄的我是一点没看懂 看看知乎又是扯一堆算法 我想一个适用所有学校的排课程序是不现实的,需求是千变万化的 我们理解的,看到的都是已经排好的结果,是Excel把 ...

  3. 绝对要收藏!!! JavaEE开发常用注解

    目录 前言 1.Mybatis常用注解 2.SpringMVC常用注解 3.Spring常用注解 1. IoC注解 2. DI注解 3. 事务注解 4.SpringBoot常用注解 5.Lombok注 ...

  4. NVIDIA具身机器人实验室 —— GEAR —— Generalist Embodied Agent Research —— NVIDIA机器人实验室

    相关: https://www.youtube.com/watch?v=jbJPG2H8hn4

  5. 再谈汤普森采样(Thompson Sampling)

    相关: [转载] 推荐算法之Thompson(汤普森)采样 [转载] 推荐系统 EE 问题与 Bandit 算法 python语言绘图:绘制一组beta分布图 转载: beta分布介绍 python语 ...

  6. vscode 单步调试时设置——是否进入非本项目的代码

    如题,在vscode中默认设置在调试时不能进入非本项目的代码(类.函数.模块),这个设置基本是OK的,因为确实没有必要进入到非本项目的代码中,但是如果有特殊需要想改变设置使其能够进入到本项目外的代码时 ...

  7. 后端开发学习敏捷需求-->产品价值的定位

    产品价值的定位 为什么要写这一系列文章 2023年网上报名学习了,敏捷软件需求的培训课程 ,一直都没有进行回顾,回顾学习,总结 业务分析的能力偏弱,学习和了解关于业务需求相关的方法和理论 每一年都有一 ...

  8. AWG(American wire gauge)美国线规

    AWG(American wire gauge)美国线规,是一种区分导线直径的标准,又被称为 Brown & Sharpe线规.这种标准化线规系统于1857年起在美国开始使用.AWG前面的数值 ...

  9. WPF 如何利用Blend给Button添加波纹效果

    先看一下效果吧: 如果不会写动画或者懒得写动画,就直接交给Blend来做吧; 其实Blend操作起来很简单,有点类似于在操作PS,我们只需要设置关键帧,鼠标点来点去就可以了,Blend会自动帮我们生成 ...

  10. python 离线安装依赖

    步骤: 1. 访问 https://pypi.org/ 2. 搜索要下载的依赖 3. 下载tar.gz文件 4. 解压,再解压(第一次解压后的dist文件夹内tar文件需解压) 5. 解压后的文件夹内 ...