JS调用C语言写的代码,cmake项目生成的wasm文件

本文详细介绍了如何在Windows环境下使用Emscripten开发工具链,从emsdk的安装和配置,到CMake项目设置,以及如何编译并导出C++函数为WebAssembly(WASM)。最后展示了如何在Node.js项目中加载和调用这些WASM模块。
摘要由CSDN通过智能技术生成
  1. 首先下载emscripten
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
  1. 安装最新版并激活
emsdk install latest
emsdk activate latest

激活cmake工具链

emsdk activate latest-upstream
  1. 在emscripten安装目录中找到Emscripten.cmake并集成到cmake项目中
    打开Visual Studio 2022,创建一个名称为EmscriptenTest的cmake项目
    编辑CMakeLists.txt文件
# CMakeList.txt: EmscriptenTest 的 CMake 项目,在此处包括源代码并定义
# 项目特定的逻辑。
#
cmake_minimum_required (VERSION 3.8)
set(CMAKE_TOOLCHAIN_FILE "D:/CppPkg/emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake")


# Enable Hot Reload for MSVC compilers if supported.
if (POLICY CMP0141)
  cmake_policy(SET CMP0141 NEW)
  set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<IF:$<AND:$<C_COMPILER_ID:MSVC>,$<CXX_COMPILER_ID:MSVC>>,$<$<CONFIG:Debug,RelWithDebInfo>:EditAndContinue>,$<$<CONFIG:Debug,RelWithDebInfo>:ProgramDatabase>>")
endif()

project ("EmscriptenTest")

# 将源代码添加到此项目的可执行文件。
add_executable (EmscriptenTest "EmscriptenTest.cpp" "util.cpp")

add_library(util STATIC util.cpp)
set_target_properties(util PROPERTIES SUFFIX ".wasm")
set_target_properties(util PROPERTIES LINK_FLAGS "--bind -s WASM=1 -s MODULARIZE=1 -s EXPORT_NAME='UtilModule' -s EXPORTED_FUNCTIONS='[\"_add\",\"_sub\"]'")


if (CMAKE_VERSION VERSION_GREATER 3.12)
  set_property(TARGET EmscriptenTest PROPERTY CXX_STANDARD 20)
endif()

# TODO: 如有需要,请添加测试并安装目标。

其中

set_target_properties(util PROPERTIES LINK_FLAGS "--bind -s WASM=1 -s MODULARIZE=1 -s EXPORT_NAME='UtilModule' -s EXPORTED_FUNCTIONS='[\"_add\",\"_sub\"]'")

这行代码表示我要在util.cpp导出add函数和sub函数。

  1. 编写util.cpp代码
    这是util.cpp代码的内容:
extern "C" {
    int add(int a, int b) {
        return a + b;
    }
    int sub(int a, int b) {
        return a - b;
    }
}

EmscriptenTest.cpp是main函数入口,就随便写个空的main函数就行了,因为这个用不到。
EmscriptenTest.cpp的内容:

#include <iostream>
#include <stdio.h>
int main() {
	return 0;
}
  1. 重新构建cmke缓存以及代码生成
    点击visual studio 的顶部的菜单栏的“项目”选项,点击“删除缓存并重新配置”,
    然后点击菜单栏中的“生成”,点击“全部重新生成”。
    在\EmscriptenTest项目的 out/build/x64-debug 目录下会生成如下的libutil.wasm文件。

在这里插入图片描述
打开cmd窗口进入到out/build/x64-debug 目录下
执行命令:

emcc libutil.wasm -o libutil.js ^
    -s EXPORT_NAME="UtilModule" ^
    -s MODULARIZE=1 ^
    -s "EXPORTED_FUNCTIONS=['_add','_sub']"

如果找不到emcc命令,请搜索emcc.bat文件在哪里,并配置Emscripten里面的emcc.bat文件所在目录的环境变量。

那么这时候呢,libutil.wasm 也会被重新覆盖生成,并且会得到一个libutil.js。这个命令一定要执行,才可以生成正确的libutil.asm,我们这里不使用libutil.js,仅使用libutil.wasm即可。
如下图,这个libutil.wasm文件确实变了,这是一个有效的wasm文件。
在这里插入图片描述
把这个libutil.wasm文件拷贝到你的nodejs项目中。
这是nodejs项目中的main.js文件的内容:

// 加载 WebAssembly 模块

const fs = require('fs');
const { promisify } = require('util');
const { instantiate } = require('node:vm');
const readFileAsync = promisify(fs.readFile);

async function main() {
  try {
    // 读取 libutil.wasm 文件
    const wasmBuffer = await readFileAsync('libutil.wasm');
    
    // 实例化 WebAssembly 模块
    const { instance } = await WebAssembly.instantiate(wasmBuffer, {});

    // 调用导出的 C++ 函数
    const resultAdd = instance.exports.add(10, 5);
    console.log("Addition result:", resultAdd);

    const resultSub = instance.exports.sub(10, 5);
    console.log("Subtraction result:", resultSub);
  } catch (error) {
    console.error('Error:', error);
  }
}

main();

这是我的package.json文件:

{
  "name": "nodedevtest",
  "version": "1.0.0",
  "description": "A minimal Electron application",
  "main": "main.js",
  "scripts": {
    "start": "node main.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "axios": "^1.6.8",
    "electron": "^30.0.1",
    "pixi.js": "^8.1.0",
    "request": "^2.88.2"
  }
}

这意味着我会用node main.js命令来执行这个main.js代码。
运行之后会得到10+5等于15的结果。

  1. 调试结果
    通过调试发现,确实调用了C++的函数,10+5等于15
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值