如何将C/C++代码转成webassembly

news2024/12/23 12:17:08

 概述

   WebAssembly/wasm WebAssembly 或者 wasm 是一个可移植、体积小、加载快并且兼容 Web 的全新格式

    官网 : WebAssembly

    快速上手: I want to… - WebAssemblyhttps://webassembly.org/getting-started/developers-guide/

      其实官网写的很详细,直接按照步骤学习应该是没有问题,以下是笔者经过实际操作总结下来可以跑通的经验,分享给读者。

   笔者的环境:win10 + VSCode

   把C/C++代码编译成WASM从而可以在浏览器或Nodejs运行时里跑,能解决性能瓶颈问题,特别是CPU密集型运算可以放在C/C++代码里实现。

 

安装Emscripten SDK (简称emsdk)   

   (笔者安装时版本为v3.1.22)

git clone https://gitee.com/openeuler-graphics/emsdk.git

   注:官方github的代码下载太慢,我用了国内的一个克隆镜像 

 命令行窗口进入下载好的目录emsdk

git checkout main

.\emsdk install latest

 执行后会出现如下提示,会自动安装node,python,java等工具 

 .\emsdk install latest
Resolving SDK alias 'latest' to '3.1.22'
Resolving SDK version '3.1.22' to 'sdk-releases-upstream-990cee04a21caafc75955d736fb45791a7f2aeee-64bit'
Installing SDK 'sdk-releases-upstream-990cee04a21caafc75955d736fb45791a7f2aeee-64bit'..
Installing tool 'node-14.18.2-64bit'..
Downloading: C:/data/develop/emsdk/zips/node-v14.18.2-win-x64.zip from https://storage.googleapis.com/webassembly/emscripten-releases-builds/deps/node-v14.18.2-win-x64.zip, 30570907 Bytes
 [----------------------------------------------------------------------------]
Unpacking 'C:/data/develop/emsdk/zips/node-v14.18.2-win-x64.zip' to 'C:/data/develop/emsdk/node/14.18.2_64bit'
Done installing tool 'node-14.18.2-64bit'.
Installing tool 'python-3.9.2-nuget-64bit'..
Downloading: C:/data/develop/emsdk/zips/python-3.9.2-4-amd64+pywin32.zip from https://storage.googleapis.com/webassembly/emscripten-releases-builds/deps/python-3.9.2-4-amd64+pywin32.zip, 14413267 Bytes
 [----------------------------------------------------------------------------]
Unpacking 'C:/data/develop/emsdk/zips/python-3.9.2-4-amd64+pywin32.zip' to 'C:/data/develop/emsdk/python/3.9.2-nuget_64bit'
Done installing tool 'python-3.9.2-nuget-64bit'.
Installing tool 'java-8.152-64bit'..
Downloading: C:/data/develop/emsdk/zips/portable_jre_8_update_152_64bit.zip from https://storage.googleapis.com/webassembly/emscripten-releases-builds/deps/portable_jre_8_update_152_64bit.zip, 69241499 Bytes
 [----------------------------------------------------------------------------]
Unpacking 'C:/data/develop/emsdk/zips/portable_jre_8_update_152_64bit.zip' to 'C:/data/develop/emsdk/java/8.152_64bit'
Done installing tool 'java-8.152-64bit'.
Installing tool 'releases-upstream-990cee04a21caafc75955d736fb45791a7f2aeee-64bit'..
Downloading: C:/data/develop/emsdk/zips/990cee04a21caafc75955d736fb45791a7f2aeee-wasm-binaries.zip from https://storage.googleapis.com/webassembly/emscripten-releases-builds/win/990cee04a21caafc75955d736fb45791a7f2aeee/wasm-binaries.zip, 422789188 Bytes
 [----------------------------------------------------------------------------]
Unpacking 'C:/data/develop/emsdk/zips/990cee04a21caafc75955d736fb45791a7f2aeee-wasm-binaries.zip' to 'C:/data/develop/emsdk/upstream'
Done installing tool 'releases-upstream-990cee04a21caafc75955d736fb45791a7f2aeee-64bit'.
Done installing SDK 'sdk-releases-upstream-990cee04a21caafc75955d736fb45791a7f2aeee-64bit'.

激活sdk 

emsdk activate latest

The changes made to environment variables only apply to the currently running shell instance. Use the 'emsdk_env.bat' to re-enter this environment later, or if you'd like to register this environment permanently, rerun this command with the option --permanent.
Resolving SDK alias 'latest' to '3.1.22'
Resolving SDK version '3.1.22' to 'sdk-releases-upstream-990cee04a21caafc75955d736fb45791a7f2aeee-64bit'
Setting the following tools as active:
   node-14.18.2-64bit
   python-3.9.2-nuget-64bit
   java-8.152-64bit
   releases-upstream-990cee04a21caafc75955d736fb45791a7f2aeee-64bit

设置环境变量 

emsdk_env.bat

 双击脚本“emcmdprompt.bat" 建立emsdk运行环境

Setting up EMSDK environment (suppress these messages with EMSDK_QUIET=1)
Adding directories to PATH:
PATH += C:\data\private\develop\emsdk
PATH += C:\data\private\develop\emsdk\upstream\emscripten
PATH += C:\data\private\develop\emsdk\node\14.18.2_64bit\bin

Setting environment variables:
PATH = C:\data\develop\emsdk;C:\data\private\develop\emsdk\upstream\emscripten;C:\data\private\develop\emsdk\node\14.18.2_64bit\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files\Git\cmd;C:\Program Files\TortoiseGit\bin;C:\Users\DELL\AppData\Local\Programs\Python\Python311\Scripts\;C:\Users\DELL\AppData\Local\Programs\Python\Python311\;C:\Users\DELL\AppData\Local\Microsoft\WindowsApps;C:\Program Files\Nodejs\node-v16.18.1-win-x64;;C:\Users\DELL\AppData\Local\Programs\Microsoft VS Code\bin
EMSDK = C:/data/develop/emsdk
EM_CONFIG = C:\data\develop\emsdk\.emscripten
EMSDK_NODE = C:\data\develop\emsdk\node\14.18.2_64bit\bin\node.exe
EMSDK_PYTHON = C:\data\develop\emsdk\python\3.9.2-nuget_64bit\python.exe
JAVA_HOME = C:\data\develop\emsdk\java\8.152_64bit
Clearing existing environment variable: EMSDK_PY

输入

emcc -v

出现如下提示表示emscripten环境已经安装好了 

emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.22 (a9981ae2a7dc3c45f833d0b2202f739d87ac05c8)
clang version 16.0.0 (https://github.com/llvm/llvm-project 8491d01cc385d08b8b4f5dd097239ea0009ddc63)
Target: wasm32-unknown-emscripten
Thread model: posix
InstalledDir: C:\data\develop\emsdk\upstream\bin

编译C/C++代码为WASM

新建一个C代码文件hello.c, 代码如下

#include <stdio.h>

int main() {
    printf("Hello World\n");
    return 0;
}

 双击脚本“emcmdprompt.bat" 进入emsdk运行环境命令行,目录切换到C代码路径下,运行命令如下:

emcc hello.c -o hello.html

 执行成功后,生成如下文件

为了测试这个wasm,我们需要部署到一个web服务里,笔者使用nodejs和koa作为web框架来发布,新建代码文件index.js,代码如下:

const Koa = require("koa");
const static = require("koa-static");
const path = require('path');
const app = new Koa();
    
//static file
app.use(
    static(path.join(__dirname, "/static/"), {
    maxage: 10080000,
    })
);

app.use((ctx) => {
    console.log(`Not Found:${ctx.URL}`);
    ctx.throw(404);
});
    
const port = 3000;
app.listen(port, () => {
      console.log(`web app started, listening at ${port}`);
});
  

将刚才hello.wasm,hello.html,hello.js三个文件复制到static目录下,运行node index.js

在浏览器里输入地址: http://127.0.0.1:3000/hello.html,可看到如下页面

实际上hello.js做了一层代码封装,使用了变量Module作为wasm的对象代理,具体细节读者不妨自行研究其代码。

 

JS调用C函数

新建hello2.c文件,内容如下

#include <stdio.h>
#include <emscripten/emscripten.h>

int main() {
    printf("Hello World\n");
    return 0;
}

#ifdef __cplusplus
#define EXTERN extern "C"
#else
#define EXTERN
#endif

EXTERN EMSCRIPTEN_KEEPALIVE void myFunction(int argc, char ** argv) {
    printf("MyFunction Called\n");
}

  双击脚本“emcmdprompt.bat" 进入emsdk运行环境命令行,目录切换到C代码路径下,运行命令如下:

emcc hello2.c -o hello2.html -s "EXPORTED_RUNTIME_METHODS=['ccall']"

 此处第一次编译会消耗较长时间,需耐心等待。

 编译成功后,将hello2.html,hello2.js,hello2.wasm文件拷贝nodejs代码的static目录下

 将hello2.html文件做下修改,修改如下

      ......
      ......
      Module.setStatus('Downloading...');
      window.onerror = function(event) {
        // TODO: do not warn on ok events like simulating an infinite loop or exitStatus
        Module.setStatus('Exception thrown, see JavaScript console');
        spinnerElement.style.display = 'none';
        Module.setStatus = function(text) {
          if (text) console.error('[post-exception status] ' + text);
        };
      };
      var myFunc = () => {
          alert("check console");
          const result = Module.ccall(
            "myFunction", // name of C function
            null, // return type
            null, // argument types
            null // arguments
          );
      };
      Module.postRun.push(myFunc);
    </script>

 启动nodejs, 在浏览器输入地址:http://127.0.0.1:3000/hello2.html

打开控制台,可以看到C函数MyFunction被调用了。

 为方便读者学习,示例代码放到了下面链接

wasm_cpp_demo: 将C/C++转成webassembly的示例

参考:

Compiling a New C/C++ Module to WebAssembly - WebAssembly | MDNWhen you've written a new code module in a language like C/C++, you can compile it into WebAssembly using a tool like Emscripten. Let's look at how it works.https://developer.mozilla.org/en-US/docs/WebAssembly/C_to_wasm

 

 

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

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

相关文章

局域网综合设计-----计算机网络

局域网综合设计 信息楼的配置 拓扑图 配置 全部在三层交换机配置 1.创建两个全局地址池vlan 52和valn53 全局地址池vlan52 全局地址池vlan53 2给vlan 52 和53 配置IP 地址 给vlan52配置ip并开启vlan52从全局地址池获取IP 子网 dns 给vlan53配置ip并开启vlan53从全局…

Android入门第37天-在子线程中调用Handler

简介 前一章我们以一个简单的小动画来解释了Handler。 这章我们会介绍在子线程里写Handler。如果是Handler写在了子线程中的话,我们就需要自己创建一个Looper对象了&#xff1a;创建的流程如下: 直接调用Looper.prepare()方法即可为当前线程创建Looper对象,而它的构造器会创…

Java并发编程—线程池

文章目录线程池什么是线程池线程池优点&#xff1a;线程复用技术线程池的实现原理是什么线程池执行任务的流程&#xff1f;线程池如何知道一个线程的任务已经执行完成线程池的核心参数拒绝策略线程池类型&#xff08;常用线程池&#xff09;阻塞队列执行execute()方法和submit(…

[附源码]计算机毕业设计springboot医疗纠纷处理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

MySQL统计函数count详解

MySQL统计函数count详解1. count()概述2. count(1)和count(*)和count(列名)的区别3. count(*)的实现方式1. count()概述 count() 是一个聚合函数&#xff0c;返回指定匹配条件的行数。开发中常用来统计表中数据&#xff0c;全部数据&#xff0c;不为null数据&#xff0c;或者去…

yocto machine class解析之flashlayout-stm32mp

yocto machine class解析之flashlayout-stm32mp 上一篇文章中我们详细介绍了st-partitions-image class。里面根据配置生成了许多的分区镜像以及分区镜像的一些参数设置。本章节介绍的flashlayout class就会根据上面生成的这些参数来生成特定的.tsv刷机文件供ST的刷机工具使用…

Bootstrap5 容器

我们可以使用以下两个容器类&#xff1a; .container 类用于固定宽度并支持响应式布局的容器。.container-fluid 类用于 100% 宽度&#xff0c;占据全部视口&#xff08;viewport&#xff09;的容器。固定宽度 .container 类用于创建固定宽度的响应式页面。 注意&#xff1a…

[node文件的上传和下载]一.node实现文件上传;二、Express实现文件下载;三、遍历下载文件夹下的文件,拼接成一个下载的url,传递到前端

目录 一.node实现文件上传 1.FormData对象&#xff1a;以对象的方式来表示页面中的表单&#xff0c;又称为表单对象。以key:value的方式来保存数据&#xff0c;XMLHttpRequest对象可以轻松的将表单对象发送到服务器端 &#xff08;1&#xff09;是一个构造函数&#xff1a;ne…

LabVIEW在应用程序和接口中使用LabVIEW类和接口

LabVIEW在应用程序和接口中使用LabVIEW类和接口 LabVIEW类和接口是用户定义的数据类型。LabVIEW类和接口开发人员创建并发布这些数据类型。LabVIEW类或接口用户无需了解如何创建LabVIEW类或接口&#xff0c;但必须了解应用程序中通过类或接口定义的数据类型应当如何使用&#…

通过java代码实现对json字符串的格式美化(完整版)

一、前言 之前转载过一篇文章&#xff0c;也是有关于通过java代码实现对json字符串的格式美化&#xff0c;但是那篇文章的实现还不够完善&#xff0c;比如其对字符串中出现特殊字符时&#xff0c;会出现转换失败。因此博主本人也是闲暇时在那份代码的基础上做了完善和补充。好…

[附源码]计算机毕业设计校园租赁系统Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Tomcat服务器的简介以及安装

文章目录1.概念1.1 什么是Web服务器&#xff1f;1.2 静态资源和动态资源1.3 常用服务器产品2. Tomcat的安装2.1 下载2.2 解压安装2.3 Tomcat的目录结构2.4 Tomcat服务器的启动和关闭2.5 tomcat启动失败的原因2.5.1 查看报错原因2.5.2 错误原因2.5.2.1 查看JAVA_HOME配置是正确2…

ESP32——WEB服务程序移植(基于示例restful_server)

一、简介 将ESP32——WEB服务程序测试项目移植到一个现有项目中&#xff0c;现有项目包括基于固定IP的WIFI连接、OTA升级、Websocket等功能。 二、移植 2.1 参考restful_server项目下分区表文件partitions_example.csv修改项目分区 因模块采用ESP32-WROVER-E(4MB)&#xff…

磨金石教育摄影技能干货分享|乡愁摄影作品欣赏——传统建筑篇

俗话说“一方水土养一方人”&#xff0c;不同的山川地域与气候环境早就不同的地域文化。我国幅员广阔&#xff0c;南北东西跨度极大&#xff0c;因此气候环境与地理环境差异很大。在民俗文化上面也呈现出多元化风格。 这种多元化的文化风格清晰的体现在各地的建筑形式上。重庆的…

Java【String】【StringBuilder】【StringBuffer】你都会用吗

文章目录前言一、常用的方法1、字符串构造2、字符串比较3、字符串查找4、字符串转化5、字符串替换6、字符串分割7、字符串截取二、字符串的不可变性三、StringBuilder、StringBuffer总结前言 在校招和笔试过程中&#xff0c;字符串是相当频繁被问到的话题&#xff0c;在之前的…

iMazing兼容Win和Mac2023免费版iOS设备管理器

iMazing是一款ios设备管理软件&#xff0c;该软件支持对基于iOS系统的设备进行数据传输与备份&#xff0c;用户可以将包括&#xff1a;照片、音乐、铃声、视频、电子书及通讯录等在内的众多信息在Windows/Mac电脑中传输/备份/管理。 软件备份是指将一部手机上的重要信息和资料&…

Pytorch -> ONNX -> TensorRT 模型转换与部署

系统环境&#xff1a; Ubuntu 18.04Cuda 11.3Cudnn 8.4.1 1 、Pytorch -> ONNX 网上相关流程很多&#xff0c;我就不重复了 可以参考Pytorch分类模型转onnx以及onnx模型推理 或者直接看Pytorch官方怎么干的。 ONNX Github onnxruntime调用onnx模型推理时有一个provider…

HTML5期末大作业:基于HTML+CSS+JavaScript茶文化中国水墨风格绿色茶叶销售(5页) 学生网页设计作业源码

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

用coding向你最爱的人说圣诞快乐

&#x1f384;&#x1f384;&#x1f384;圣诞节即将到来&#xff0c;今天让我们用编码的方式向你最爱的人表达圣诞节快乐。 圣诞节的起源 圣诞节源自古罗马人迎接新年的农神节&#xff0c;与基督教本无关系。在基督教盛行罗马帝国后&#xff0c;教廷将这种民俗节日纳入基督教体…

DenseNet的基本思想

之前的文章介绍过残差网络的基本思想&#xff1a;残差网络的思想就是将网络学习的映射从X到Y转为学习从X到Y-X的差&#xff0c;然后把学习到的残差信息加到原来的输出上即可。即便在某些极端情况下&#xff0c;这个残差为0&#xff0c;那么网络就是一个X到Y的恒等映射。其示意图…