You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Electron使用ffi-napi调用Win32 API返回成功但结构体无返回值问题

问题原因

  1. FFI函数参数声明错误:SHAppBarMessage和GetWindowRect的第二个参数均为结构体指针类型,你当前声明为值类型,系统API只会写入临时拷贝的内存空间,原结构体实例不会被修改。
  2. Win32 API类型匹配错误:HWND、LPARAM等随系统位数变化的指针长度类型,不能固定声明为int、long、int64,否则会出现内存布局错位,即使传指针也无法读取正确数据。

修正后的代码

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

const ABM_GETTASKBARPOS = 5;

// 定义结构体及对应指针类型
const RECT_Struct = Struct({
  left: ref.types.long,
  top: ref.types.long,
  right: ref.types.long,
  bottom: ref.types.long,
});
const LPRECT = ref.refType(RECT_Struct);

const APPBARDATA_Struct = Struct({
  cbSize: ref.types.uint32,
  hWnd: ref.types.uintptr, // HWND为适配32/64位的指针长度类型
  uCallbackMessage: ref.types.uint32,
  uEdge: ref.types.uint32,
  rc: RECT_Struct,
  lParam: ref.types.intptr, // LPARAM为适配32/64位的指针长度类型
});
const PAPPBARDATA = ref.refType(APPBARDATA_Struct);

// 声明FFI函数时使用指针类型作为参数
export const shell32 = ffi.Library("shell32.dll", {
  SHAppBarMessage: [ref.types.long, [ref.types.uint32, PAPPBARDATA]],
});

export const user32 = ffi.Library("user32.dll", {
  GetWindowRect: [ref.types.bool, [ref.types.uintptr, LPRECT]],
});

// 调用逻辑保持不变
const data = new APPBARDATA_Struct();
data.cbSize = APPBARDATA_Struct.size;
const result = shell32.SHAppBarMessage(ABM_GETTASKBARPOS, data);

const rect = new RECT_Struct();
// 替换为你实际的窗口句柄
const targetHwnd = 0x20674;
const result2 = user32.GetWindowRect(targetHwnd, rect);

console.log(`SHAppBarMessage 调用结果:${result},任务栏位置:`, data.rc);
console.log(`GetWindowRect 调用结果:${result2},窗口矩形:`, rect);

额外注意事项

如果在Electron渲染进程中调用,需要满足以下条件:

  • 渲染进程开启nodeIntegration: true、contextIsolation: false,或通过preload脚本暴露FFI调用方法
  • ffi-napi、ref-napi、ref-struct-di等依赖必须针对当前使用的Electron版本重新编译,可使用electron-rebuild工具完成编译

内容的提问来源于stack exchange,提问作者Elendiar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 06:15:02