节点 ffi napi,调用返回 true 但指针中没有结果

Posted

技术标签:

【中文标题】节点 ffi napi,调用返回 true 但指针中没有结果【英文标题】:Node ffi napi, call return true but no result in pointer 【发布时间】:2021-10-25 22:27:09 【问题描述】:

需要在电子中使用一些 ffi napi,我试图让它工作,从小开始。试图理解并获得 ffi 有效,但无法获得结果。我知道我将指针传递给结构,结果将写入其中。但是调用 return True 并且在指定的指针中没有结果。没有新数据。请帮忙。

const ffi = require("ffi-napi");
const ref = require("ref-napi");
const Struct = require("ref-struct-di")(ref);

const ABM_NEW = 0;
const ABM_QUERYPOS = 0x2;
const ABM_GETTASKBARPOS = 5; // 0x00000005
const ABM_GETSTATE = 0x4;

const ABEdgeLeft = 0;

const RECT_Struct = Struct(
  left: "long",
  top: "long",
  right: "long",
  bottom: "long",
);

const APPBARDATA_Struct = Struct(
  cbSize: "uint32",
  hWnd: "int",
  uCallbackMessage: "uint32",
  uEdge: "uint32",
  rc: RECT_Struct,
  lParam: "int64",
);

export const shell32 = ffi.Library("shell32.dll", 
  SHAppBarMessage: ["long", ["int", APPBARDATA_Struct]],
);

export const user32 = ffi.Library("user32.dll", 
  GetWindowRect: ["bool", ["long", RECT_Struct]],
);

const data = new APPBARDATA_Struct();
data.cbSize = APPBARDATA_Struct.size;

const result = shell32.SHAppBarMessage(ABM_GETTASKBARPOS, data);

const rect = new RECT_Struct();
const result2 = user32.GetWindowRect(0x20674, rect);
console.log(`result: $JSON.stringify(result): $JSON.stringify(data)`);
console.log(`result2: $JSON.stringify(result2): $JSON.stringify(rect)`);

结果

result: 1: "cbSize":40,"hWnd":0,"uCallbackMessage":0,"uEdge":0,"rc":"left":0,"top":0,"right":0,"bottom":0,"lParam":0
result2: true: "left":0,"top":0,"right":0,"bottom":0

当我测试时,函数调用有效 - 它返回 1 (true) 和 hwnd 存在的窗口,如果关闭则返回 0。但我无法从缓冲区中获取结果数据,这让我很生气。

【问题讨论】:

【参考方案1】:

首先,我不太了解指针。但是,我对同样的问题感兴趣,所以我尝试并找到了解决方案。等我知道具体原理后再修改。

您使用的 GetWindowRectSHAppBarMessage 函数从 C++ 接收结构指针类型参数。这些函数具有通过返回值通知成功与否以及在接收到的struct上记录数据的功能。因此,在 C++ 中测试函数时,在构建结构类型参数而不添加与符号(例如 &rect 或 &data)符号时会发生错误。

ref-struct-di 的示例显示了使用指向参数的结构指针的示例。我认为这是将结构指针传递给函数,并且在如下修改代码时它可以工作。使用struct作为参数的部分和用ffi定义函数的部分必须修改。请参考代码中的cmets!

// GetWindowRect Example

const RECT = Struct(
  left: ref.types.long,
  top: ref.types.long,
  right: ref.types.long,
  bottom: ref.types.long,
);

const user32 = ffi.Library('user32.dll', 
  GetWindowRect: ['bool', ['long', ref.refType(RECT)]], // RECT_Struct -> ref.refType(RECT_Struct) or 'pointer'
);

const rect = new RECT;
console.log(user32.GetWindowRect(0x007B0F10, rect.ref())); // 0x007B0F10 is one of my windows that I found with Spy++.

console.log('left', rect.left);
console.log('right', rect.right);
console.log('top', rect.top);
console.log('bottom', rect.bottom);

// SHAppBarMessage Example

const ABM_GETTASKBARPOS = 5;
const APPBARDATA = Struct(
  cbSize: ref.types.uint32,
  hWnd: ref.types.long,
  uCallbackMessage: ref.types.uint32,
  uEdge: ref.types.uint32,
  rc: RECT,
  lParam: ref.types.int64,
);

const shell32 = ffi.Library('shell32.dll', 
  SHAppBarMessage: ['long', ['int', ref.refType(APPBARDATA)]], // APPBARDATA_Struct -> ref.refType(APPBARDATA_Struct) or 'pointer'
);

const data = new APPBARDATA();
data.cbSize = APPBARDATA.size;

console.log(shell32.SHAppBarMessage(ABM_GETTASKBARPOS, data.ref()));

console.log('cbSize', data.cbSize);
console.log('hWnd', data.hWnd);
console.log('uCallbackMessage', data.uCallbackMessage);
console.log('uEdge', data.uEdge);
console.log('rc.left', data.rc.left);
console.log('rc.right', data.rc.right);
console.log('rc.top', data.rc.top);
console.log('rc.bottom', data.rc.bottom);
console.log('lParam', data.lParam);

【讨论】:

是的,问题出在这,“指针”而不是 ref.refType(*) 也可以。谢谢! 老兄,你这个天才,这解决了我几分钟前发布的问题! (***.com/questions/69695067/…) 我更改为[INT, WPARAM, ref.refType(KBDLLHOOKSTRUCT)], 和`$JSON.stringify(lParam.deref())` 并且它有效!谢谢,你让我见识了!!!这个问题让我抓狂,它在 x64 上完美运行,我知道为什么。现在我明白了!

以上是关于节点 ffi napi,调用返回 true 但指针中没有结果的主要内容,如果未能解决你的问题,请参考以下文章

指向结构的节点 ffi 指针

Nodejs使用ffi调用so库

Nodejs使用ffi调用so库

JavaScript调用C语言的几种方式

PHP FFI调用go,居然比go还快

electron调用dll文件