Nodejs 使用 node-ffi 调用 DLL 的操作

发布于 1周前 作者 htzhanglong 来自 nodejs/Nestjs

Nodejs 使用 node-ffi 调用 DLL 的操作

node 需要使用一个原生模块 折腾了好久

环境什么的搞了大半天 弄好了

可以调用 DLL 的方法 运行

但是发现 有一个 DLL 暴露的是一个 Class 不知道要怎么调用

今天查了好久资料

正常导出方法的 DLL 头文件是这样的

extern "C" int __declspec(dllexport)My_Test(char *a, int b, int c);
extern "C" void __declspec(dllexport)My_Hello(char *a, int b, int c);

nodejs 的调用方法

const dll = ffi.Library( './test.dll', {
    // My_Test 是 dll 中定义的函数,两者名称需要一致
    // [a, [b,c....]] a 是函数出参类型,[b,c]是 dll 函数的入参类型
    My_Test: ['int', ['string', 'int', 'int']], // 可以用文本表示类型
    My_Hello: [ref.types.void, ['string', ref.types.int, ref.types.int]] // 更推荐用`ref.types.xx`表示类型,方便类型检查,`char*`的特殊缩写下文会说明
})

但是我哪一个模块导出的是一个 class 不知道要怎么去调用它

class __declspec(dllexport) Person

#pragma once 

class __declspec(dllexport) Person { private: int age; public: int getAge(); void setAge(int a); };


10 回复

没办法调用,因为 C++ 没有一个统一的 ABI,不同编译器编译出来的都不能互相调用,甚至同一个编译器不同版本也不一定兼容。
解决方法是用 C 语言的接口封装一遍。比如 cef https://bitbucket.org/chromiumembedded/cef 就是这么做的。


你是想导出这个类来给 node 使用?
编译成 DLL 之后,类这个概念已经不存在了。
FFI 是用来调用函数的,在 linux 就是用了 dlopen 和 dlsym 这些封装的,win 下提供了类似的函数,它们本质上都是在 so 或者 dll 文件里查找动态符号表,所以你想要使用这个类,只有再导出一个 c 标准的函数,然后在这个函数里实现你想做的要用到这个类的操作。

#1
#2
意思是没办法调用 C++的类 需要运行的话只能让 C++程序员封装层函数来调用么

#2 不是我想导出类 这个 DLL 是公司 c++发给我调试的

是的,类是 cpp 的概念,dll 里面只有函数的概念了

你可以自己写,msdn 上说用_declspec(dllimport)可以调用这个导出的对象,前提是你们编译器这些得一样。你可以通过 pe 工具查看它用的编译器这些,我记得 dll 是有这个信息的。然后自己用 extern “c”来导出 c 风格的函数。

我之前也有这么个需求,后来直接让 C++提供 node 模块了

在 Node.js 中使用 node-ffi 调用 DLL(动态链接库)是一种常见的方法,它允许你从 Node.js 直接调用本地 C/C++ 函数。以下是一个基本的示例,展示如何设置和使用 node-ffi 来调用 DLL。

首先,确保你已经安装了 node-ffiref 这两个 npm 包:

npm install ffi ref

假设你有一个名为 example.dll 的 DLL,它包含一个函数 int add(int a, int b)

下面是一个 Node.js 脚本,演示如何调用这个函数:

const ffi = require('ffi');
const ref = require('ref');

// 加载 DLL
const myLibrary = ffi.Library('path/to/example.dll', {
  'add': ['int', ['int', 'int']]  // 定义 add 函数,它接受两个 int 参数并返回一个 int
});

// 调用 DLL 中的 add 函数
const result = myLibrary.add(5, 3);
console.log('Result of add(5, 3):', result);  // 输出: Result of add(5, 3): 8

在这个示例中,我们首先使用 ffi.Library 加载 DLL,并定义了一个名为 add 的函数,它接受两个整数参数并返回一个整数。然后,我们调用这个函数并打印结果。

请注意,path/to/example.dll 应该替换为你的 DLL 文件的实际路径。

这种方法非常强大,因为它允许你在 Node.js 应用程序中直接使用现有的本地代码库。然而,它也有一些限制,比如类型安全性和性能问题,因此在决定使用这种方法之前,请仔细考虑你的需求。

回到顶部