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が必要になる。