【备忘干货】c/c++ (wasm)和js互相调用记录

c/c++(wasm)和js互相调用记录

  • 废话 :)
  • 准备工作:安装Emscripten
  • 初探:C++(wasm)之hello world
  • 进一步探究:接口调用
    • 1.js调用c++,一些基本类型的传递(char*,int,float)以及返回值
    • 2.js向c++注入函数,c++调用js方法
    • 3.wasm大工程代码如何管理和编译
  • 结语


废话 😃

WebAssembly(缩写 Wasm)是基于堆栈虚拟机的二进制指令格式。Wasm为了一个可移植的目标而设计的,可用于编译C/C++/rust/go等语言,使客户端和服务器应用程序能够在Web上部署。
wasm的一些优势:
1.可以使用 C/C++、rust、go等语言编写代码,性能优越;
2.二进制文件,文本占用的存储空间更小;
3.安全 和 JS 有相同的沙盒环境和安全策略,比如同源策略;
4.绝大多数主流浏览器支持。


准备工作:安装Emscripten

要把C/C++代码编译成wasm,就需要一个工具链,这里使用的是比较主流的Emscripten。(本文测试环境是winows11环境
1.安装Emscripten工具链:
官网连接:https://emscripten.org

# Get the emsdk repo
git clone https://github.com/emscripten-core/emsdk.git# Enter that directory
cd emsdk
# Fetch the latest version of the emsdk (not needed the first time you clone)
git pull# Download and install the latest SDK tools.
./emsdk install latest# Make the "latest" SDK "active" for the current user. (writes .emscripten file)
./emsdk activate latest# Activate PATH and other environment variables in the current terminal
source ./emsdk_env.sh

注意:如果是Windows系统 用 emsdk.bat 代替 ./emsdk, and emsdk_env.bat 代替source ./emsdk_env.sh

安装过程会自动下载python,nodejs,java和clang编译器。如果碰到卡住或者报错就是网络问题,可能要采取“科学上网”才能安装完成。

执行完emsdk_env.bat后,就可以进行安装完成验证:emcc -v
需要注意的是emsdk_env.bat只对本终端生效,如果不想每次执行,可以把emsdk相关的路径声明到系统环境变量,不过系统之前若安装过python,nodejs也有可能产生冲突。具体看自己环境情况而定。

在这里插入图片描述


初探:C++(wasm)之hello world

严格来说以下实例是C接口的函数导出调用, 然后借助c接口调用c++方法。事实上能导出c接口了那么意味着我们就可以在c接口里面去实例化C++类和结构,然后再通过导出的C接口调用C++类里面的方法。

当然Emscripten其实还提供了另外2种绑定方式embind和WebIDL Binder,可以直接将c++类绑定到js进行调用,这里就不再做详细探讨。

1.首先需要编写C++代码,并确保代码可以在本地进行编译和测试

#include <iostream>int main(int argc, char ** argv)
{std::cout << "Hello World, hello WASM!\n";return 0;
}
  1. 使用Emscripten编译C++代码,将代码编译成WebAssembly二进制文件,具体文件路径根据自己而定。
em++ C:\Users\003\Desktop\wasm\wasmdemo.cpp -s WASM=1 -o C:\Users\003\Desktop\wasm\wasmdemo.html

在这里插入图片描述
成功的生成了3个文件:html,js,wasm
在这里插入图片描述
这里-o是指定输出文件,指定不同输出得到文件不一样:

参数输出
-o xx.htmlxx.html, xx.js, xx.wasm
-o xx.jsxx.js, xx.wasm
-o xx.wasmxx.wasm

3.测试一下html加载wasm的运行效果
首先先开启http代理服务,不能直接去打开这个html:

emrun --no_browser --port 8080 C:\Users\003\Desktop\wasm\wasmdemo.html

然后再浏览器输入:http://localhost:8080/wasmdemo.html
毫无意外的成功显示出c++代码中的打印。。。Hello World, hello WASM
在这里插入图片描述

进一步探究:接口调用

1.js调用c++,一些基本类型的传递(char*,int,float)以及返回值

wasmdemo.h头文件

#ifndef __WASM_DEMO__
#define __WASM_DEMO__
#include <emscripten.h>#if defined(__cplusplus)
#define WASM_API(rettype) extern "C" rettype EMSCRIPTEN_KEEPALIVE
#else
#define WASM_API(rettype) rettype EMSCRIPTEN_KEEPALIVE
#endifWASM_API(int) mathAdd(int a, int b);WASM_API(int) str2Num(char* str1);WASM_API(float) mathMulti(float a, float b);#endif

wasmdemo.cpp源文件

#include "wasmdemo.h"
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>int mathAdd(int a, int b)
{return (a+b);
}//假定是int范围数字
int str2Num(char* str1)
{if(str1 == NULL)return -INT_MAX;int num = atoi(str1);return num;
}float mathMulti(float a, float b)
{return (a*b);
}

然后编译代码,这里把c标准库里面的malloc和free导出提给给js调用,后续字符串操作需要用到

em++ C:\Users\003\Desktop\wasm\wasmdemo.cpp -s WASM=1 -s EXPORTED_FUNCTIONS="['_malloc','_free']" -o C:\Users\003\Desktop\wasm\wasmdemo.js

新建一个wasmdemo.html

<!doctype html><html><head><meta charset="utf-8"><title>Wasm:demo</title></head><body><script>Module = {};Module.onRuntimeInitialized = function() {var str = '31415';var strBuff = new TextEncoder().encode(str);var strPtr = Module._malloc(strBuff.length + 1);Module.HEAPU8.set(strBuff, strPtr);Module.HEAPU8[strPtr + strBuff.length] = 0;console.log('str2Num:', Module._str2Num(strPtr));Module._free(strPtr);console.log('mathAdd:', Module._mathAdd(250, 250));console.log('mathMulti:', Module._mathMulti(3.14, 3.0));}</script><script src="wasmdemo.js"></script></body>
</html>

这个html调用了cpp文件里面的三个函数并输出运行结果,需要注意的是字符串传递需要在js层预先申请内存,然后传递到cpp
浏览器html执行结果如下:
在这里插入图片描述
既然可以传递char*了,那么其他类型数组的传递也是不在话下了,都是要预先在js申请好内存,然后传递指针,这里就不再进行探究了。

2.js向c++注入函数,c++调用js方法

新建一个js模块wasmapi.js,然后添加函数如下图所示, 并在c++侧加入此函数声明。这样编译之后即可调用jsLogPrint函数。

em++ C:\Users\003\Desktop\wasm\wasmdemo.cpp --js-library C:\Users\003\Desktop\wasm\wasmapi.js -s WASM=1 -s EXPORTED_FUNCTIONS="['_malloc','_free']" -o C:\Users\003\Desktop\wasm\wasmdemo.js

在这里插入图片描述
浏览器执行访问html结果:
在这里插入图片描述

3.wasm大工程代码如何管理和编译

简单的 c++ 项目,可以直接调用 em++将 c++ 编译为 wasm,但是对于大型项目,都是使用 cmake 等构建工具进行构建的。 好消息是 emscripten 很好的和 cmake 进行了集成,我们只需要进行如下替换:

cmake => 替换为 emcmake cmake
make => 替换为 emmake make

编译步骤:

cd build && emcmake ..    
emmake make // 生成xx.a
emcc xx.a -o xx.js // 生成 xx.wasm和lxx.js  

再仔细研究下的话其实直接使用cmake构建也是可以的,通过官方cmake文件可知,只需要加入
-DCMAKE_TOOLCHAIN_FILE=yourpath/cmake/Modules/Platform/Emscripten.cmake

还有一点需注意的是,Unix系cmake集成编译会简单些,如果是windows那么需要额外安装MinGW编译器,笔者尝试过使用VC++编译失败,Emscripten官方cmake文件提示也只有Unix Makefiles和MinGW Makefiles俩种。
在这里插入图片描述

结语

通过本文可对wasm使用过程有一个初步的了解, 但还有很多功能尚未尝试。例如:前面提到的
embind和WebIDL Binder, ccall, cwrap等等。还有一个有趣的东东Qt for WebAssembly,可以把Qt的东西在浏览器上跑包括GUI程序。
好了剩下的交给时间咯 !😃


作者:费码程序猿
欢迎技术交流:QQ:255895056
转载请注明出处,如有不当欢迎指正

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/195362.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

安装Python以及pycharm

Pycharm是编辑器。相当于Word对文字进行编辑。 Python是解释器。讲代码翻译为计算机可以理解的指令。 1、安装Python 官网&#xff1a;Welcome to Python.org 打开的时候有点慢等待一会就好&#xff0c;点击下载&#xff0c;选择Windows版本 等待一会&#xff0c;可以看到如…

docker内容整理

docker内容整理 docker的安装 检查之前是否安装过docker&#xff0c;如果有使用yum remove docker卸载 [rootwoniu ~]# yum remove docker \ > docker-client \ > docker-client-latest \ > docker-common \ > docker-latest \ > docker-latest-logrotate \ &g…

行业分析:轻轨行业发展现状及市场投资前景

轻轨是城市轨道建设的一种重要形式&#xff0c;也是当今世界上发展最为迅猛的轨道交通形式。轻轨的机车重量和载客量要比一般列车小&#xff0c;因此叫做“轻轨”。 城市轻轨具有运量大、速度快、污染小、能耗少、准点运行、安全性高等优点。城市轻轨与地下铁道、城市铁路及其…

day5 判断2个字符串是否字母完全相同

bool isAnagram(string s, string t) { int record[26] {0}; for (int i 0; i < s.size(); i) { // 并不需要记住字符a的ASCII&#xff0c;只要求出一个相对数值就可以了 record[s[i] - a]; } for (int i 0; i < t.size(); i) { record[t[i] - a]--; } for (int i 0;…

ICC2:如何创建多个core区,分别做power plan

我正在「拾陆楼」和朋友们讨论有趣的话题,你⼀起来吧? 拾陆楼知识星球入口 如下图,core区域(core row)仅需要存在两个地方,右上大的core区,以及ram上下。 这里需要进行两步操作,分别是create site array创建指定位置的core row,上图所示部分,第二步是创建pg region…

深入理解GMP模型

1、GMP模型的设计思想 1&#xff09;、GMP模型 GMP分别代表&#xff1a; G&#xff1a;goroutine&#xff0c;Go协程&#xff0c;是参与调度与执行的最小单位M&#xff1a;machine&#xff0c;系统级线程P&#xff1a;processor&#xff0c;包含了运行goroutine的资源&#…

从零构建属于自己的GPT系列3:模型训练2(训练函数解读、模型训练函数解读、代码逐行解读)

&#x1f6a9;&#x1f6a9;&#x1f6a9;Hugging Face 实战系列 总目录 有任何问题欢迎在下面留言 本篇文章的代码运行界面均在PyCharm中进行 本篇文章配套的代码资源已经上传 从零构建属于自己的GPT系列1&#xff1a;文本数据预处理 从零构建属于自己的GPT系列2&#xff1a;语…

Centos系列:Centos7下部署nginx(三种方式安装部署,图文结合超详细,适合初学者)

Centos7下部署nginx&#xff08;三种方式安装部署&#xff0c;图文结合超详细&#xff0c;适合初学者&#xff09; Centos7下部署nginx一. ngxin是什么二. nginx的作用正向代理和反向代理的区别 三. 安装部署安装环境1. yum安装配置nginx源启动nginx浏览器访问&#xff0c; IP:…

打印菱形图案C语言

C代码实现&#xff1a; #include <stdio.h> void printDiamond(int n) { int i, j, space n - 1; // 打印上半部分包括中间行 for (i 0; i < n; i) { // 打印空格 for (j 0; j < space; j) printf(" "); // 打印星号 for (j 1; j < 2 *…

Canvas鼠标画线

鼠标按下开始画线,鼠标移动根据鼠标的轨迹去画,鼠标抬起停止画线 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0">…

Java多线程技术三:锁——ReentrantLock的使用

1 概述 在Java多线程中可以使用synchronzied关键字来实现线程间同步&#xff0c;不过在JDK1.5中新增的ReentrantLock类也能达到同样的效果&#xff0c;并且在扩展功能上更加强大。

举例说明自然语言处理(NLP)技术。

本文章由AI生成&#xff01; 以下是自然语言处理&#xff08;NLP&#xff09;技术的一些例子&#xff1a; 机器翻译&#xff1a;将一种语言翻译成另一种语言的自动化过程。常见的机器翻译系统包括谷歌翻译&#xff0c;百度翻译等。 语音识别&#xff1a;将口头语言转换成文本…

备忘录怎么传到电脑?备忘录手机电脑互传方法

对于那些记性不好的人来说&#xff0c;手机上的备忘录简直是个不可或缺的好帮手。可是有时候&#xff0c;我们在手机上记录的内容需要在电脑上查看&#xff0c;这时候该怎么办呢&#xff1f; 曾经&#xff0c;我也为备忘录的手机电脑互传问题头疼不已。手机上记录的事项&#…

Pytorch当中transpose()和permute()函数的区别

在 PyTorch 中&#xff0c;transpose() 和 permute() 都是用于张量维度的转换&#xff0c;但有一些区别&#xff1a; transpose() 方法&#xff1a; transpose() 方法允许你交换张量的两个维度&#xff0c;使其维度发生变化。当你使用 transpose(dim1, dim2) 时&#xff0c;它会…

element UI改写时间线组件为左右分布

2023.12.4今天我学习了如何使用element的时间线组件&#xff0c;效果如&#xff1a; 代码如下&#xff1a;&#xff08;关键代码 v-if"item.send_type"&#xff09;判断左右分布情况。因为如果没有这个判断的话&#xff0c;其实会两边都有显示。可以用一个判断表示0显…

基于ssm的疫苗预约系统(有报告)。Javaee项目。ssm项目。

演示视频&#xff1a; 基于ssm的疫苗预约系统&#xff08;有报告&#xff09;。Javaee项目。ssm项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;通过Spring Spri…

语音芯片的BUSY状态指示功能特征:提升用户体验与系统稳定性的关键

在电子产品的音频系统中&#xff0c;语音芯片扮演着至关重要的角色。为了保证音频的流畅播放和功能的正常运行&#xff0c;语音芯片的各种状态指示功能变得尤为重要。其中&#xff0c;BUSY状态指示功能是语音芯片中的一项关键特征&#xff0c;它对于提升用户体验和系统稳定性具…

Pytorch深度强化学习1-5:详解蒙特卡洛强化学习原理

目录 0 专栏介绍1 蒙特卡洛强化学习2 策略评估原理3 策略改进原理3.1 同轨蒙特卡洛强化学习3.2 离轨蒙特卡洛强化学习 0 专栏介绍 本专栏重点介绍强化学习技术的数学原理&#xff0c;并且采用Pytorch框架对常见的强化学习算法、案例进行实现&#xff0c;帮助读者理解并快速上手…

C++STL容器

一、顺序性容器 简述&#xff1a;顺序容器为程序员提供了控制元素存储和访问顺序的能力。这种顺序不依赖元素的值&#xff0c;而是与元素加入容器时的位置相对应。所有顺序容器都提供了快速顺序访问元素的能力 1.vector(向量) 基本概念和介绍 对于vector容器&#xff0c;它…

大模型概述

文章目录 AI大模型的定义AI大模型的分类LoRA 微调 AI大模型的定义 AI大模型是通过深度学习算法和人工神经网络训练出的具有庞大规模参数的人工智能模型。这些模型使用大量的多媒体数据资源作为输入&#xff0c;并通过复杂的数学运算和优化算法来完成大规模的训练&#xff0c;以…