Electron使用ffi-napi调用Win32 API返回成功但结构体无返回值问题
问题原因
- FFI函数参数声明错误:
SHAppBarMessage和GetWindowRect的第二个参数均为结构体指针类型,你当前声明为值类型,系统API只会写入临时拷贝的内存空间,原结构体实例不会被修改。 - 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
相关产品推荐
相关产品推荐

