nodejs调用rust的完整代码实例

 更新时间:2025年08月13日 09:22:51   作者:起个名字不容易啊  
Rust主要用在一些需要高性能效果的地方,这篇文章主要介绍了nodejs调用rust的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下

nodejs调用rust

调用rust的方式目前分为打包dll库调用和wasm

性能和跨平台兼容性分别有不同优缺点可根据各自需求

nodejs 调用rust的方式目前分为打包dll库调用和wasm

1. 调用 Rust 打包的 DLL 库

  • 优点:

    • 性能更高:DLL 是直接编译为本地机器代码的动态链接库,几乎没有额外的运行时开销。
    • 直接访问系统资源:可以使用操作系统的底层功能,调用成本低。
    • 适用于高性能需求:如果需要频繁调用复杂的计算逻辑,DLL 是更优的选择。
    • 跨语言调用成熟:通过 Node.js 的 ffi-napinapi-rs 等库,可以高效与 Rust 的 DLL 交互。
  • 缺点:

    • 跨平台兼容性复杂:需要为 Windows(DLL)、macOS(.dylib)和 Linux(.so)分别构建对应的动态库。
    • 部署复杂:需要在目标环境中正确配置动态库的路径。
    • 线程安全性:如果你的 DLL 代码设计不当,可能导致线程冲突。

2. 调用 Rust 编译的 WASM

  • 优点:

    • 跨平台性:WASM 是平台无关的,运行时在所有支持 WebAssembly 的环境中都一致。
    • 容易部署:Rust 编译为 WASM 后,生成一个 .wasm 文件,可以直接加载,不需要担心动态库路径。
    • 安全性:WASM 在沙盒环境中运行,不直接访问底层资源,隔离更好。
  • 缺点:

    • 性能开销

      • WebAssembly 的沙盒环境导致运行时性能稍逊于本地代码。
      • 如果需要频繁调用小粒度函数,调用开销可能显著。
    • 与 Node.js 的绑定层次较浅:通过 @wasmer/wasi@wasm-tool/wasm-pack-plugin 等工具加载后,可能需要额外处理复杂的内存管理或数据交换问题。

性能比较

  • 执行效率: DLL > WASM
    DLL 是本地执行的动态链接库,几乎没有额外开销;WASM 有一定的沙盒化运行开销。
  • 调用成本: DLL < WASM
    调用 DLL 是直接的本地调用,而调用 WASM 涉及到序列化和反序列化。
  • 部署复杂性: DLL > WASM
    DLL 需要根据操作系统生成多个文件,WASM 只需一个文件即可运行。

如果你的 Rust 逻辑以高密度计算为主,例如数据处理、压缩等,推荐 DLL。如果是需要兼容多个环境,并且以一次性任务为主,推荐 WASM。

代码示例

  1. 先写点rust代码,并自动开启多线程处理数据
use rayon::prelude::*;

#[no_mangle]  
pub extern "C" fn add_to_array(arr: *const i32, len: usize, num: i32, result: *mut i32) {
    let slice = unsafe { std::slice::from_raw_parts(arr, len) };
    let output = unsafe { std::slice::from_raw_parts_mut(result, len) };

    // 并行操作输出数组
    output
        .par_iter_mut()
        .enumerate()
        .for_each(|(i, out)| {
            *out = slice[i] + num;
        });
}

Cargo.toml 文件

[package]
name = "rust_napi"
version = "0.1.0"
edition = "2021"

[dependencies]
napi = { version = "2.11.0" }
rand = "0.8"
rayon = "1.7"

[lib]
crate-type = ["cdylib"] // mac 打包cdylib, windows 打包dll

如何将rust打包cdylib或者dll

// mac 指定架构
cargo build --release --target x86_64-apple-darwin
// window
cargo build --release

打包后会在当前目录生成target文件夹

x86_64-apple-darwin这个文件夹就是打包后生成的指定架构的包

  1. node 调用cdylib,并执行

node 调用cdylib需要使用到ffi-napi

// cargo build --release --target x86_64-apple-darwin
const path = require("path");

const ffi = require("ffi-napi");
const ref = require("ref-napi");

// 动态确定库文件路径 "/rust_napi/target/x86_64-apple-darwin/release/librust_napi.dylib"

const libName =
  process.platform === "win32"
    ? "librust_napi.dll"
    : process.platform === "darwin"
    ? "/rust_napi/target/x86_64-apple-darwin/release/librust_napi.dylib"
    : "librust_napi.so";

const libPath = path.join(__dirname, libName);

// 加载 Rust 库
const rustLib = ffi.Library(libPath, {
  add_to_array: ["void", ["pointer", "size_t", "int", "pointer"]],
});

function addToArray(arr, num) {
  const arrayLength = arr.length;
  const inputBuffer = Buffer.alloc(arrayLength * 4); // 每个 i32 占 4 字节
  const outputBuffer = Buffer.alloc(arrayLength * 4);

  // 将 JavaScript 数组写入输入缓冲区
  arr.forEach((value, index) => {
    inputBuffer.writeInt32LE(value, index * 4);
  });

  // 调用 Rust 函数
  rustLib.add_to_array(inputBuffer, arrayLength, num, outputBuffer);

  // 从输出缓冲区读取结果数组
  const result = [];
  for (let i = 0; i < arrayLength; i++) {
    result.push(outputBuffer.readInt32LE(i * 4));
  }
  return result;
}

const generateRandomIntArray = (size, min, max) => {
  return Array.from({ length: size }, () =>
    Math.floor(Math.random() * (max - min) + min)
  );
};

let listy = generateRandomIntArray(4e7, 1, 100);

let start = Date.now();
addToArray(listy, 100);
console.log(Date.now() - start, 4); // rust 974

module.exports = { addToArray };

总结 

到此这篇关于nodejs调用rust的文章就介绍到这了,更多相关nodejs调用rust内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 使用nvm进行多个nodejs版本的统一管理

    使用nvm进行多个nodejs版本的统一管理

    随着前端项目的越来越多,不同项目使用的nodejs版本可能不一样,导致在切换不同项目时需要更换不同的nodejs版本,非常麻烦,本次推荐使用nvm进行多个nodejs版本的统一管理,文中有详细的图文介绍,需要的朋友可以参考下
    2023-12-12
  • nodeJS中关于path.resolve()的用法解析

    nodeJS中关于path.resolve()的用法解析

    这篇文章主要介绍了nodeJS中关于path.resolve()的用法,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-06-06
  • Node.js使用NodeMailer发送邮件实例代码

    Node.js使用NodeMailer发送邮件实例代码

    本篇文章主要介绍了Node.js使用NodeMailer发送邮件实例代码,具有一定的参考价值,有兴趣的可以了解一下。
    2017-03-03
  • nodejs express路由匹配控制及Router模块化使用详解

    nodejs express路由匹配控制及Router模块化使用详解

    这篇文章主要为大家介绍了nodejs express路由匹配控制及Router模块化使用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-10-10
  • windows使用nvm对node进行版本管理切换的完整步骤

    windows使用nvm对node进行版本管理切换的完整步骤

    这篇文章主要介绍了windows使用nvm对node进行版本管理切换的完整步骤,在使用之前各位务必卸载掉自己安装过的nvm或者node版本包括环境变量之类的,要保证自己的电脑完全没有node环境,需要的朋友可以参考下
    2024-03-03
  • 用node-webkit把web应用打包成桌面应用(windows环境)

    用node-webkit把web应用打包成桌面应用(windows环境)

    这篇文章主要介绍了windows环境下用node-webkit把web应用打包成桌面应用的教程,需要的朋友可以参考下
    2018-02-02
  • nodejs中密码加密处理操作详解

    nodejs中密码加密处理操作详解

    这篇文章主要介绍了nodejs中密码加密处理操作,结合实例形式分析了nodejs针对用户登陆密码的加密处理操作相关实现技巧与注意事项,需要的朋友可以参考下
    2018-03-03
  • npm查看镜像源与切换镜像源方法详解

    npm查看镜像源与切换镜像源方法详解

    这篇文章主要为大家介绍了npm查看镜像源与切换镜像源方法详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-06-06
  • 运行Node.js的IIS扩展iisnode安装配置笔记

    运行Node.js的IIS扩展iisnode安装配置笔记

    这篇文章主要介绍了运行Node.js的IIS扩展iisnode安装配置笔记,iisnode的扩展可以把Node.js程序托管到IIS,托管之后也意味着可以使用IIS里面的各种功能,需要的朋友可以参考下
    2015-03-03
  • nodejs之get/post请求的几种方式小结

    nodejs之get/post请求的几种方式小结

    下面小编就为大家带来一篇nodejs之get/post请求的几种方式小结。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-07-07

最新评论