node-ffi-napi: Error with Electron and ffi-napi

Electron: ^22.0.3 Tried also with Electron 20.0.0 ffi-napi: 4.0.3

File index.js

const { app, BrowserWindow } = require('electron')
var ffi = require('ffi-napi');


const createWindow = () => {
    const win = new BrowserWindow({
        width: 800,
        height: 600
    })

    win.loadFile('index.html')
}


app.whenReady().then(() => {
    createWindow()
})


var libm = ffi.Library('libm', {
    'ceil': ['double', ['double']]
});
libm.ceil(1.5); // 2

// You can also access just functions in the current process by passing a null
var current = ffi.Library(null, {
    'atoi': ['int', ['string']]
});
current.atoi('1234'); // 1234

File index.html

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
    <title>Hello World!</title>
</head>

<body>
    <h1>Hello World!</h1>
    We are using Node.js <span id="node-version"></span>,
    Chromium <span id="chrome-version"></span>,
    and Electron <span id="electron-version"></span>.
</body>

</html>

Error:

App threw an error during load
Error: Error in native callback
    at process.func [as dlopen] (node:electron/js2c/asar_bundle:2:1822)
    at Module._extensions..node (node:internal/modules/cjs/loader:1226:18)
    at Object.func [as .node] (node:electron/js2c/asar_bundle:2:1822)
    at Module.load (node:internal/modules/cjs/loader:1011:32)
    at Module._load (node:internal/modules/cjs/loader:846:12)
    at f._load (node:electron/js2c/asar_bundle:2:13330)
    at Module.require (node:internal/modules/cjs/loader:1035:19)
    at require (node:internal/modules/cjs/helpers:102:18)
    at load (C:\Users\Farella Vito\Desktop\Instance Manager v2\node_modules\node-gyp-build\node-gyp-build.js:22:10)
    at Object.<anonymous> (C:\Users\Farella Vito\Desktop\Instance Manager v2\node_modules\ref-napi\lib\ref.js:8:53)

About this issue

  • Original URL
  • State: open
  • Created a year ago
  • Reactions: 8
  • Comments: 56

Commits related to this issue

Most upvoted comments

Thank you @lwahonen for your fork. It works, but everytime i make a new clone from my repo and run “npm i” an error occured and i had to run “npm i” twice (that broke my build), now i found a new fork npm i @breush/ref-napi npm i @breush/ffi-napi

Now my build + ffi-napi integration is working again.

"electron": "^24.4.1", "@breush/ffi-napi": "^4.0.13", "@breush/ref-napi": "^4.0.9"

The same problem. I used template like @hatsune-miku TypeScript, Vite, Electron Win10, npm v9.4.0, node v16.15.1

{
    "electron": "^22.2.0",
    "ffi-napi": "^4.0.3",
    "ref-napi": "^3.0.3",
}

I also found out that the latest compatible electron version is equal to 20.3.8. And starting from the electron version 20.3.9 the application crashes with an error.

Maybe this comparison will help knowledgeable people to understand the problem: https://github.com/electron/electron/compare/v20.3.8...v20.3.9

These two are working for me:

https://www.npmjs.com/package/@lwahonen/ffi-napi https://www.npmjs.com/package/@lwahonen/ref-napi

For some reason I need to npm install twice on Windows, as the first build always poops out with “file in use” errors. Feel free to figure out why that happens.

I’m in trouble too. I was wondering if there is another good library and I found this one. i will try. koffi

Adding another recommendation for Koffi. It’s been working well for me so far in the latest version of Electron, and it has pretty extensive documentation: https://koffi.dev

(Before trying koffi I had tried using the @breush/ref-napi fork, which @stevenlafl got working on a newer electron version, however when I tried it I hit the same error that @ej-toita hit here.)

But yeah; it’s biggest benefit at the moment is simply that it’s not abandoned, and has good documentation.

Like @Elendiar mentioned, I also like its handling of structures and pointers – I found it easier to figure out how to implement them properly. (due partly just to its documentation I guess)

An example usage of koffi from my rewrite:

export const Rect = koffi.struct("Rect", {left: "ulong", top: "ulong", right: "ulong", bottom: "ulong"});
export const LPRect = koffi.pointer("LPRect", "Rect");
// Leaving out the HWND def, since I'm a rebel and define it as `int64` for easier usage, rather than a proper pointer-type. How bad is this? XD

const lib = koffi.load("user32.dll");
export const user32 = {
	GetWindowRect: lib.func("bool GetWindowRect(HWND hWnd, _Out_ LPRect lpRect)"),
	//GetWindowRect: lib.func("GetWindowRect", "bool", [HWND, koffi.out(LPRect)]), // alternative syntax
};

export type RectShape = {left: number, top: number, right: number, bottom: number};
export function getWindowRect(handle) {
	const rect = {} as RectShape;
	var success = user32.GetWindowRect(handle, rect);
	if (!success) return null;

	return rect;
}

While the node-ffi equivalent is about the same amount of code, I think the koffi API is a little more intuitive. (eg. not split into multiple libraries like ffi-napi + ref-napi + ref-struct-di, more standard name with koffi.pointer instead of ref.refType, and being able to pass in the rect structure itself as an argument rather than rect.ref())

Since it doesnt seem likely to me that this problem is going to be solved, I have moved onto node-addon-api. It works very well and I recommend to try it out.

Adding another recommendation for https://github.com/Koromix/koffi I switched to that without too much of an issue with only academic C++ experience. My app is now running Electron v28.

Update: locking electron version to 20.0.0 worked for me.

  1. Write "electron": "20.0.0", (without caret^) in package.json
  2. Run a yarn install or equivalent and you will see electron is re-compiling
  3. It works. Just spent a whole day on it

PS: I have seen some tutorials saying you should run node-gyp or electron-rebuild manually to get it worked but actually you don’t have to. I only did yarn add ffi-napi. PS: My project is newly created by yarn create electron-vite project_name --template typescript


Same problem on both electron 20.0.0 and 20.0.2. “ffi-napi”: “^4.0.3”.

Uncaught Error: Error in native callback
    at process.func [as dlopen]
    ...

at the line const ffi = require('ffi-napi')

change to electron@15.4.0 & ffi-napi@4.0.3 can fix it

The solution should not be to downgrade your electron. It is important to stay up to date with the latest electron for many reasons.

@angelfraga I just finished migrating my electron project to koffi. So far I have achieved 100% work in the x64 build, but in ia32 build the program crashes without any error after launch. Now I’m trying to figure this out, but I’m sure it’s due to incorrect types, because i dont test functions in x86 environment. I liked Koffi in general. Working with structures and pointers is more convenient.

I finally got some time to try

 "electron": "^25.3.1",
 "@breush/ffi-napi": "^4.0.13",
 "@breush/ref-napi": "^4.0.9"

myself, and it caused no native build was found for platform=win32 arch=x64 runtime=electron error. @electron/rebuild did no good.

@ej-toita My fix didn’t work(

Yes that seems to be the fix for the runtime error. Someone forked ref-napi (dependency of ffi-napi) and made the same change separately here: node-ffi-napi/ref-napi@latest…Vitalii4as:ref-napi:latest

Thanks for pointing this out! Would love to see this merged and released in ref-napi and a subsequent ffi-napi release so we don’t have to fork and build our own versions.

I’ve eneded up replacing ffi-napi to koffi Then had to change mainWindow mainWindow = new BrowserWindow({ ... webPreferences: { nodeIntegration: true, }, });

and i was finally able to upgrade electron from 19.x to 20.x

@angelfraga I used @inigolabs/ref-napi fork when electron updates with context isolation, it works but when i recently want update project (electron taskbar client for production computers, which register self as system taskar with registerWindowMessageA and shAppBarMessage, also register wineventHook etc), i cant build it due node-gyp error.

I managed to rewrite all these functions in koffi, but now I need to try to execute them on x86 OS, or by commenting codeblocks and assembling to understand where the problem is. At least the module that is responsible for registering the taskbar in the system works in x86 fine.

Even if these are working and they are not malicious code, you should be aware that these projects are not 100% github forks and their integrity is not guaranteed, in other words they do not share the same history with this repo. Maybe it is something their author could fix.

I don’t have the time / motivation for this. Maybe @angelfraga could create the version you seek, instead of asking someone else?

@Breush can you prebuild for ia32 in your pkg? i can use your pkg in dev. but myapp is build ia32, and in runtime throw error: No native build was found for platform=win32 arch=ia32...

i try to prebuild, but throw error:

Traceback (most recent call last):
  File "C:\Users\10121\AppData\Roaming\nvm\v16.13.0\node_modules\node-gyp\gyp\gyp_main.py", line 45, in <module>
    sys.exit(gyp.script_main())
  File "C:\Users\10121\AppData\Roaming\nvm\v16.13.0\node_modules\node-gyp\gyp\pylib\gyp\__init__.py", line 686, in script_main
    return main(sys.argv[1:])
  File "C:\Users\10121\AppData\Roaming\nvm\v16.13.0\node_modules\node-gyp\gyp\pylib\gyp\__init__.py", line 678, in main
    return gyp_main(args)
  File "C:\Users\10121\AppData\Roaming\nvm\v16.13.0\node_modules\node-gyp\gyp\pylib\gyp\__init__.py", line 645, in gyp_main
    [generator, flat_list, targets, data] = Load(
  File "C:\Users\10121\AppData\Roaming\nvm\v16.13.0\node_modules\node-gyp\gyp\pylib\gyp\__init__.py", line 155, in Load
    result = gyp.input.Load(
  File "C:\Users\10121\AppData\Roaming\nvm\v16.13.0\node_modules\node-gyp\gyp\pylib\gyp\input.py", line 3002, in Load
    LoadTargetBuildFile(
  File "C:\Users\10121\AppData\Roaming\nvm\v16.13.0\node_modules\node-gyp\gyp\pylib\gyp\input.py", line 475, in LoadTargetBuildFile
    gyp.common.ResolveTarget(build_file_path, dependency, None)[0]
  File "C:\Users\10121\AppData\Roaming\nvm\v16.13.0\node_modules\node-gyp\gyp\pylib\gyp\common.py", line 87, in ResolveTarget
    [parsed_build_file, target, parsed_toolset] = ParseQualifiedTarget(target)
  File "C:\Users\10121\AppData\Roaming\nvm\v16.13.0\node_modules\node-gyp\gyp\pylib\gyp\common.py", line 62, in ParseQualifiedTarget
    target_split = target.rsplit(":", 1)
AttributeError: 'int' object has no attribute 'rsplit' while trying to load binding.gyp

then i edit common.py from target.rsplit(":", 1) to str(target).rsplit(":", 1), but then throw error:

gyp: page not found (cwd: D:\project\customNapiPkg\ref-napi) while loading dependencies of binding.gyp while trying to load binding.gyp

ant i don’t know how to fix it.

can you help me

i get this error: Error: External buffers are not allowed at process.func [as dlopen] (node:electron/js2c/asar_bundle:2:1822) at Object.Module._extensions…node (node:internal/modules/cjs/loader:1354:18) at Object.func [as .node] (node:electron/js2c/asar_bundle:2:1822) at Module.load (node:internal/modules/cjs/loader:1124:32) at Module._load (node:internal/modules/cjs/loader:965:12) at Function.f._load (node:electron/js2c/asar_bundle:2:13330) at Module.require (node:internal/modules/cjs/loader:1148:19) at require (node:internal/modules/cjs/helpers:110:18)

while using: Electron 25.2.0 “dependencies”: { “@inigolabs/ffi-napi”: “4.0.7”, “@inigolabs/ref-napi”: “4.0.4”, }, “overrides”: { “@inigolabs/ref-napi”: “4.0.4” },

also tried: “dependencies”: { “@lwahonen/ffi-napi”: “^4.0.12”, “@lwahonen/ref-napi”: “^4.0.8”, },

but getting the same error

As I said, you need to run npm install twice. Feel free to figure out what’s blocking the access to nothing.obj on the first go.

For what it’s worth, it appears to work in one go using pnpm @lwahonen