首页 > 解决方案 > Node.js ffi 访问 dll

问题描述

我们有一个 dll 的 C# 包装器,我想将其转换为 node.js 包装器以进行增强。我似乎无法让 irSAInitialize 函数返回句柄或成功响应。这是我第一次尝试使用 ffi,但相信我已经正确设置了所有内容(dll 中的另一个函数似乎可以工作)。

这是我尝试初始化然后记录结果的简单 POC 代码。

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

var intPtr = ref.refType('long');
var dllPath = "O:\\ApiBin\\";
var dllFile = dllPath + "irApiSA.dll";
var randConnect = ffi.Library(dllFile, {
    'irSAInitialize': ['int', ['string', 'string', 'string', 'string', 'string', 'string', intPtr]],
    'irUnInitialize': ['int', []]
});

var handleOut = ref.alloc('long');
var a=b=c=d=e=f="";

var result = randConnect.irSAInitialize(a, b, c, d, e, f, handleOut);
console.log("Init Result: " + result);
handle = handleOut.deref();
console.log("Init Handle: " + handle);

var uninitResult = randConnect.irUnInitialize();
console.log("Uninit Result: " + uninitResult);

这是我看到的结果。注意 uninit 函数似乎成功返回(结果 1),因此它似乎与 DLL 进行了适当的通信。

Init Result: 0
Init Handle: 0
Uninit Result: 1

这是.h的相关部分供参考

typedef long IR_HANDLE;
typedef enum {IR_FAILURE_CODE = 0, IR_SUCCESS_CODE = 1} IR_ERROR_CODE;

IR_DECL_SPEC IR_ERROR_CODE irSAInitialize                   (const char *szDARouterFilePath, const char *szDADataFilePath, const char *szRouterFilePath, const char *szMapFilePath, const char *szAdminFilePath, const char *szDataFilePath, IR_HANDLE *pirHandle);

同样作为参考,这里是在现有解决方案中工作的 C# 代码片段

[DllImport("irApiSA.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int irSAInitialize(String a, String b, String c, String d, String e, String f, ref int handle);
...
char[] temp = new char[256];
String s = new String(temp);
int result = irSAInitialize(s, s, s, s, s, s, ref handle);

我已经尝试了许多使用 int 与 long、string 与 buffer 等的变体……没有运气。任何帮助或建议表示赞赏!

标签: node.jsffi

解决方案


不知道为什么,但发现如果我以管理权限运行它,我就能成功运行它。此特定 dll 的其他一些说明:

  • 它是 32 位的,所以你必须运行 32 位 Node.js
  • 路径环境变量必须包含 DLL 的路径(以便它可以找到它的依赖项)

希望这可以节省其他人几个小时的痛苦!


推荐阅读