【备忘干货】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
#endif

WASM_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.mfbz.cn/a/215154.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

企业安全生产管理系统功能介绍

安全生产管理系统通过借助信息化手段和技术算法&#xff0c;建立了一个集安全风险监测预警、安全分区管理、隐患排查治理、特殊作业、人员定位管控于一体的“一张图”平台。平台可以实现企业安全生产管控的全面监管&#xff0c;推动公司生产安全业务的动态管理、集中管理和协同…

014 OpenCV canny边缘检测

一、环境 本文使用环境为&#xff1a; Windows10Python 3.9.17opencv-python 4.8.0.74 二、canny原理 OpenCV中的Canny边缘检测算法是一种基于图像处理的计算机视觉技术&#xff0c;主要用于检测图像中的边缘。Canny边缘检测算法的原理是通过计算图像中像素点之间的梯度值来…

GPT4-Turbo技术原理研发现状及未来应用潜力分析报告

今天分享的是GPT4-Turb系列深度研究报告&#xff1a;《GPT4-Turbo技术原理研发现状及未来应用潜力分析报告》。 &#xff08;报告出品方&#xff1a;深度行业分析研究&#xff09; 报告共计&#xff1a;46页 图像理解能力提升&#xff1a;三大视觉学习方法  为打造视觉大模…

53.redis分布式缓存

目录 一、单机安装Redis。 二、Redis主从集群。 2.1.集群结构 2.2.准备实例和配置 2.3.启动 2.4.开启主从关系 2.5.测试 三、搭建哨兵集群。 3.1.集群结构 3.2.准备实例和配置 3.3.启动 3.4.测试 四、搭建分片集群。 4.1.集群结构 4.2.准备实例和配置 4.3.启动…

网络层之SDN基本概念、路由算法和路由协议

学习的最大理由是想摆脱平庸&#xff0c;早一天就多一份人生的精彩&#xff1b;迟一天就多一天平庸的困扰。各位小伙伴&#xff0c;如果您&#xff1a; 想系统/深入学习某技术知识点… 一个人摸索学习很难坚持&#xff0c;想组团高效学习… 想写博客但无从下手&#xff0c;急需…

淘宝API接口申请指南

一、申请条件数据接口 已注册淘宝账号并完成实名认证&#xff1b;拥有良好的淘宝信用记录&#xff1b;符合淘宝API接口的相关规定。 二、申请流程 登录淘宝账号&#xff0c;进入“卖家中心”页面&#xff1b;点击“我要开店”-“申请应用”&#xff0c;选择“淘宝API”&…

LangChain(0.0.340)官方文档五:Model

LangChain官网、LangChain官方文档 、langchain Github、langchain API文档、llm-universe 文章目录 一、Chat models1.1 Chat models简介1.2 Chat models的调用方式1.2.1 环境配置1.2.2 使用LCEL方式调用Chat models1.2.3 使用内置Chain调用Chat models 1.3 缓存1.3.1 内存缓存…

【Linux】:线程(一)概念

线程概念 一.线程1.简单理解2.一些疑问3.简单说一下优缺点&#xff0c;异常和用途 二.进程VS线程1.进程和线程的联系和区别2.phread线程库(创建)3.线程的LWP4.线程等待5.线程终止 三.C11里的线程四.创建线程最底层接口 一般教程里定义线程&#xff1a;是进程内的一个执行分支。…

PicoScope 7 软件报警功能可实现自动保存和循环捕捉

最近很多用户提到&#xff0c;怎么让虹科Pico示波器采集信号到缓冲区满了之后自动保存在电脑里&#xff0c;然后清出缓存空间继续采集&#xff0c;如此循环工作。这里不得不向大家介绍一下PicoScope软件的强大功能之一&#xff1a;报警功能&#xff01; 报警在软件的工具菜单下…

盘点最近两个世纪那些搞怪又精彩的专利

人类的创新是无止境的&#xff0c;下面收集的就是最近两个世纪全球那些奇怪搞笑、精彩的6项专利。 小胡子卫士 (1876) 这款“胡须防护罩”由 VA.Gates 于 1876 年获得专利&#xff0c;是在节日盛宴期间保护胡须的巧妙解决方案。“弯曲和凹形的护罩&#xff0c;可以由硫化橡胶、…

visual c++ 2019 redistributable package

直接安装下面包只有24M Microsoft Visual C Redistributable 2019 x86: https://aka.ms/vs/16/release/VC_redist.x86.exe x64: https://aka.ms/vs/16/release/VC_redist.x64.exe ———————————————— 版权声明&#xff1a;本文为CSDN博主「kpacnB_Z」的原创文章…

堆排序(C语言)

前言 在上一篇内容&#xff1a;大小堆的实现&#xff08;C语言&#xff09;&#xff0c;我们实现了关于创建大小堆的各函数与实现。但是如果突然要使用一个堆排序但是此时并没有一个现成的堆&#xff0c;这就需要花费时间去新建实现堆的插入删除这些操作从而实现一个堆&#xf…

Oracle-CDB容器数据库修改service_names踩坑

前言: 最近在对一套Oracle容器数据库进行迁移测试时&#xff0c;为了保持新环境与旧环境的服务名一致&#xff0c;需要在新环境添加旧环境的服务名&#xff0c;在CDB的根容器通过service_name参数添加旧环境的服务名之后&#xff0c;发现数据库PDB的服务名全部被注销&#xff0…

今日思考 -- 创新领导力(CIO)读后感

收获3个观点&#xff1a; 1 &#xff0c;IT DT 商业&#xff0c;才是未来IT人的出路之一 &#xff01; 2 &#xff0c;在CXO中&#xff0c;CIO像CEO一样&#xff0c;具备了整个企业的业务全视角 &#xff0c;同时也更具解决 ‘’系统性‘’问题的能力 &#xff01; 3 &…

go并发编程(中)

目录 一、并发安全性 1.1 变量并发安全性 1.2 容器并发安全性 二、多路复用 三、协程常见的面试题 3.1交替打印奇数偶数 一、并发安全性 1.1 变量并发安全性 这个和C中并发安全是一样的&#xff0c;主要是多个线程对临界资源的同时访问&#xff0c;最经典的就是 n操作…

网络层之IP数据报格式、数据报分片、IPv4、子网划分和子网掩码

学习的最大理由是想摆脱平庸&#xff0c;早一天就多一份人生的精彩&#xff1b;迟一天就多一天平庸的困扰。各位小伙伴&#xff0c;如果您&#xff1a; 想系统/深入学习某技术知识点… 一个人摸索学习很难坚持&#xff0c;想组团高效学习… 想写博客但无从下手&#xff0c;急需…

openmmlab环境搭建及模拟kitti数据集跑pointpillars模型

点云训练—openmmlab环境搭建及模拟kitti数据集跑pointpillars模型 1 环境搭建 在我的 linux 服务器上&#xff0c;基于ubuntu20.04 参见&#xff1a;开始你的第一步 — MMDetection3D 1.3.0 文档 1.1 本地环境已安装anaconda. anaconda的安装参见博文&#xff1a;DS6.1-Y…

Linux 基本语句_14_信号灯实验

原理&#xff1a; Send进程通过建立共享内存区域&#xff0c;并向其中写入数据&#xff0c;Recive通过与共享内存连接读取其中的数据。 但是如果进程进行读取操作的时候其他进程再次写入会产生数据丢失&#xff0c;产生竞态&#xff0c;为了确保在某段时间内只有一个操作&…

Leetcode—1038.从二叉搜索树到更大和树【中等】

2023每日刷题&#xff08;四十九&#xff09; Leetcode—1038.从二叉搜索树到更大和树 算法思想 二叉搜索树的中序遍历&#xff08;左根右&#xff09;结果是一个单调递增的有序序列&#xff0c;我们反序进行中序遍历&#xff08;右根左&#xff09;&#xff0c;即可以得到一…

基于Java SSM框架实现母婴儿用品网站系统项目【项目源码+论文说明】计算机毕业设计

基于java的SSM框架实现母婴儿用品网站系统演示 摘要 随着社会的发展&#xff0c;社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 母婴用品网站&#xff0c;主要的模块包括管理员&#xff1b;主页、个人中心、用户管理、商品分…