ElectronでC++拡張モジュールを呼び出せるかやってみる。
electron/using-native-node-modules.md at master · electron/electron · GitHub
まず、npm init。
$ pwd
/home/bg1/project/cloud/github.com/Sample/electron-rebuild/electron-rebuild/electron-rebuild/src/app_
$ npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.
See `npm help json` for definitive documentation on these fields
and exactly what they do.
Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.
Press ^C at any time to quit.
package name: (app_)
version: (1.0.0)
description: electron-rebuild sample
entry point: (index.js) main.js
test command: start
git repository: -
keywords: -
author: B.G
license: (ISC) MIT
About to write to
/home/bg1/project/cloud/github.com/Sample/electron-rebuild/electron-rebuild/electron-rebuild/src/app_/package.json:
{
"name": "app_",
"version": "1.0.0",
"description": "electron-rebuild sample",
"main": "main.js",
"scripts": {
"test": "start"
},
"repository": {
"type": "git",
"url": "-"
},
"keywords": [
"-"
],
"author": "B.G",
"license": "MIT"
}
Is this OK? (yes)
$package.jsonを作成したら、
main.jsで、
デベロッパーツールを起動するようにしておく。
index.htmlは、
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>app_</title> </head> <body> <h1>ABCDE</h1> <button onclick="run()">Run</button> <script> document.write(process.versions.electron); function run(){ var nativeExt = require('./build/Release/native_ext.node'); var str = nativeExt.get_abc(); alert(str); } </script> </body> </html>
ネイティブ拡張を参照できるようにしておく。
package.jsonは、
{ "name": "app_", "version": "1.0.0", "description": "electron-rebuild sample", "main": "main.js", "scripts": { "start": "electron ." }, "repository": { "type": "git", "url": "-" }, "keywords": [ "-" ], "author": "B.G", "license": "MIT" }
npm startで"electron ."を起動できるように。
electronをインストールする。
$ vi main.js $ vi index.html $ vi package.json $ npm install electron > electron@4.1.0 postinstall /home/bg1/project/cloud/github.com/Sample/electron-rebuild/electron-rebuild/electron-rebuild/src/app_/node_modules/electron > node install.js Downloading tmp-4643-1-SHASUMS256.txt-4.1.0 [============================================>] 100.0% of 4.74 kB (4.74 kB/s) npm notice created a lockfile as package-lock.json. You should commit this file. + electron@4.1.0 added 145 packages from 141 contributors and audited 201 packages in 81.199s found 0 vulnerabilities ╭───────────────────────────────────────────────────────────────╮ │ │ │ New minor version of npm available! 6.4.1 → 6.9.0 │ │ Changelog: https://github.com/npm/cli/releases/tag/v6.9.0 │ │ Run npm install -g npm to update! │ │ │ ╰───────────────────────────────────────────────────────────────╯ $
続いて、node-gypのインストール。
$ ls index.html main.js node_modules package-lock.json package.json $ npm install node-gyp + node-gyp@3.8.0 added 35 packages from 10 contributors and audited 384 packages in 4.585s found 0 vulnerabilities $
binding.gypはnode-gypのトピックで使ったものと同じものを使用した。
また、native_ext.ccでは、
get_abcの中でsleepで5秒休止するようにした。
node-gyp configureする。
[bg1@localhost app_]$ vi binding.gyp [bg1@localhost app_]$ vi native_ext.cc [bg1@localhost app_]$ ./node_modules/.bin/node-gyp configure gyp info it worked if it ends with ok gyp info using node-gyp@3.8.0 gyp info using node@10.15.0 | linux | x64 gyp info spawn /usr/bin/python2 gyp info spawn args [ '/home/bg1/project/cloud/github.com/Sample/electron-rebuild/electron-rebuild/electron-rebuild/src/app_/node_modules/node-gyp/gyp/gyp_main.py', gyp info spawn args 'binding.gyp', gyp info spawn args '-f', gyp info spawn args 'make', gyp info spawn args '-I', gyp info spawn args '/home/bg1/project/cloud/github.com/Sample/electron-rebuild/electron-rebuild/electron-rebuild/src/app_/build/config.gypi', gyp info spawn args '-I', gyp info spawn args '/home/bg1/project/cloud/github.com/Sample/electron-rebuild/electron-rebuild/electron-rebuild/src/app_/node_modules/node-gyp/addon.gypi', gyp info spawn args '-I', gyp info spawn args '/home/bg1/.node-gyp/10.15.0/include/node/common.gypi', gyp info spawn args '-Dlibrary=shared_library', gyp info spawn args '-Dvisibility=default', gyp info spawn args '-Dnode_root_dir=/home/bg1/.node-gyp/10.15.0', gyp info spawn args '-Dnode_gyp_dir=/home/bg1/project/cloud/github.com/Sample/electron-rebuild/electron-rebuild/electron-rebuild/src/app_/node_modules/node-gyp', gyp info spawn args '-Dnode_lib_file=/home/bg1/.node-gyp/10.15.0/<(target_arch)/node.lib', gyp info spawn args '-Dmodule_root_dir=/home/bg1/project/cloud/github.com/Sample/electron-rebuild/electron-rebuild/electron-rebuild/src/app_', gyp info spawn args '-Dnode_engine=v8', gyp info spawn args '--depth=.', gyp info spawn args '--no-parallel', gyp info spawn args '--generator-output', gyp info spawn args 'build', gyp info spawn args '-Goutput_dir=.' ] gyp info ok $
node-gyp buildする。
$ ./node_modules/.bin/node-gyp build
gyp info it worked if it ends with ok
gyp info using node-gyp@3.8.0
gyp info using node@10.15.0 | linux | x64
gyp info spawn make
gyp info spawn args [ 'BUILDTYPE=Release', '-C', 'build' ]
make: ディレクトリ '/home/bg1/project/cloud/github.com/Sample/electron-rebuild/electron-rebuild/electron-rebuild/src/app_/build'
に入ります
CXX(target) Release/obj.target/native_ext/native_ext.o
In file included from ../native_ext.cc:2:
/home/bg1/.node-gyp/10.15.0/include/node/node.h:570:43: 警告: cast
between incompatible function types from ‘void
(*)(v8::Local<v8::Object>)’ to ‘node::addon_register_func’ {aka ‘void
(*)(v8::Local<v8::Object>, v8::Local<v8::Value>, void*)’}
[-Wcast-function-type]
(node::addon_register_func) (regfunc), \
^
/home/bg1/.node-gyp/10.15.0/include/node/node.h:604:3: 備考: in
expansion of macro ‘NODE_MODULE_X’
NODE_MODULE_X(modname, regfunc, NULL, 0) // NOLINT (readability/null_usage)
^~~~~~~~~~~~~
../native_ext.cc:28:1: 備考: in expansion of macro ‘NODE_MODULE’
NODE_MODULE(native_ext, init);
^~~~~~~~~~~
SOLINK_MODULE(target) Release/obj.target/native_ext.node
COPY Release/native_ext.node
make: ディレクトリ '/home/bg1/project/cloud/github.com/Sample/electron-rebuild/electron-rebuild/electron-rebuild/src/app_/build'
から出ます
gyp info ok
$ビルドすると、
$ ls binding.gyp build index.html main.js native_ext.cc node_modules package-lock.json package.json $ cd build/ $ cd Release/ $ ls native_ext.node obj.target $ pwd /home/bg1/project/cloud/github.com/Sample/electron-rebuild/electron-rebuild/electron-rebuild/src/app_/build/Release $
build/Releaseの下にnative_ext.nodeができる。
npm startすると、

このように表示される。
右の開発ツールでConsoleのタブをクリック。

いまのところは問題なさそうだが、"Run"ボタンを押すと、

エラーが発生。
実は、ElectronのNODE_MODULEとNode.jsのNODE_MODULEのバージョンには違いがあり、それが原因でネイティブモジュールを呼び出せない。
そこで、electron-rebuildを使って、"ElectronのヘッダでNode.jsをリビルドする"という作業を行う。
(ここ、よくわからないとおもうが、次のようにすればうまくいくと思えばいい・・・。)
まず、electron-rebuildをインストール。
$ ls binding.gyp build index.html main.js native_ext.cc node_modules package-lock.json package.json $ npm install --save-dev electron-rebuild + electron-rebuild@1.8.4 added 75 packages from 53 contributors and audited 679 packages in 9.573s found 0 vulnerabilities $
ビルド時にしか使わないので、"--save-dev"でインストール。
npmの--save, --save-dev, --save-optionalの違い - how to code something
electron-rebuildコマンドを実行し、configureとbuild。
$ ./node_modules/.bin/electron-rebuild
✔ Rebuild Complete
$ ./node_modules/.bin/node-gyp configure
gyp info it worked if it ends with ok
gyp info using node-gyp@3.8.0
gyp info using node@10.15.0 | linux | x64
gyp info spawn /usr/bin/python2
gyp info spawn args [
'/home/bg1/project/cloud/github.com/Sample/electron-rebuild/electron-rebuild/electron-rebuild/src/app_/node_modules/node-gyp/gyp/gyp_main.py',
gyp info spawn args 'binding.gyp',
gyp info spawn args '-f',
gyp info spawn args 'make',
gyp info spawn args '-I',
gyp info spawn args
'/home/bg1/project/cloud/github.com/Sample/electron-rebuild/electron-rebuild/electron-rebuild/src/app_/build/config.gypi',
gyp info spawn args '-I',
gyp info spawn args
'/home/bg1/project/cloud/github.com/Sample/electron-rebuild/electron-rebuild/electron-rebuild/src/app_/node_modules/node-gyp/addon.gypi',
gyp info spawn args '-I',
gyp info spawn args '/home/bg1/.node-gyp/10.15.0/include/node/common.gypi',
gyp info spawn args '-Dlibrary=shared_library',
gyp info spawn args '-Dvisibility=default',
gyp info spawn args '-Dnode_root_dir=/home/bg1/.node-gyp/10.15.0',
gyp info spawn args
'-Dnode_gyp_dir=/home/bg1/project/cloud/github.com/Sample/electron-rebuild/electron-rebuild/electron-rebuild/src/app_/node_modules/node-gyp',
gyp info spawn args
'-Dnode_lib_file=/home/bg1/.node-gyp/10.15.0/<(target_arch)/node.lib',
gyp info spawn args
'-Dmodule_root_dir=/home/bg1/project/cloud/github.com/Sample/electron-rebuild/electron-rebuild/electron-rebuild/src/app_',
gyp info spawn args '-Dnode_engine=v8',
gyp info spawn args '--depth=.',
gyp info spawn args '--no-parallel',
gyp info spawn args '--generator-output',
gyp info spawn args 'build',
gyp info spawn args '-Goutput_dir=.' ]
gyp info ok
$ ./node_modules/.bin/node-gyp build
gyp info it worked if it ends with ok
gyp info using node-gyp@3.8.0
gyp info using node@10.15.0 | linux | x64
gyp info spawn make
gyp info spawn args [ 'BUILDTYPE=Release', '-C', 'build' ]
make: ディレクトリ '/home/bg1/project/cloud/github.com/Sample/electron-rebuild/electron-rebuild/electron-rebuild/src/app_/build'
に入ります
CXX(target) Release/obj.target/native_ext/native_ext.o
In file included from ../native_ext.cc:2:
/home/bg1/.node-gyp/10.15.0/include/node/node.h:570:43: 警告: cast
between incompatible function types from ‘void
(*)(v8::Local<v8::Object>)’ to ‘node::addon_register_func’ {aka ‘void
(*)(v8::Local<v8::Object>, v8::Local<v8::Value>, void*)’}
[-Wcast-function-type]
(node::addon_register_func) (regfunc), \
^
/home/bg1/.node-gyp/10.15.0/include/node/node.h:604:3: 備考: in
expansion of macro ‘NODE_MODULE_X’
NODE_MODULE_X(modname, regfunc, NULL, 0) // NOLINT (readability/null_usage)
^~~~~~~~~~~~~
../native_ext.cc:28:1: 備考: in expansion of macro ‘NODE_MODULE’
NODE_MODULE(native_ext, init);
^~~~~~~~~~~
SOLINK_MODULE(target) Release/obj.target/native_ext.node
COPY Release/native_ext.node
make: ディレクトリ '/home/bg1/project/cloud/github.com/Sample/electron-rebuild/electron-rebuild/electron-rebuild/src/app_/build'
から出ます
gyp info ok
$そうすると、
$ ls bin binding.gyp build index.html main.js native_ext.cc node_modules package-lock.json package.json $ cd bin $ ls linux-x64-69 $ cd linux-x64-69/ $ ls app_.node $ pwd /home/bg1/project/cloud/github.com/Sample/electron-rebuild/electron-rebuild/src/app_/bin/linux-x64-69 $
bin/linux-x64-69の下にapp_.nodeができる。これがリビルドされたモジュールなのでこれを参照するようにする。
このように書き換えたら、npm startしてみる。
$ pwd /home/bg1/project/cloud/github.com/Sample/electron-rebuild/electron-rebuild/electron-rebuild/src/app_ $ ls bin binding.gyp build index.html main.js native_ext.cc node_modules package-lock.json package.json $ vi index.html $ ls bin binding.gyp build index.html main.js native_ext.cc node_modules package-lock.json package.json $ npm start > app_@1.0.0 start /home/bg1/project/cloud/github.com/Sample/electron-rebuild/electron-rebuild/electron-rebuild/src/app_ > electron .
で起動し、

このようになるので、Runボタンを押す。

今度は、エラーが出ず、へこんだままになるので、5秒待つ。
5秒経つと、

alertで"ABC"が表示される。
このように、Electronからネイティブ拡張を使う場合は、electron-rebuildが必要になる。