LoginSignup
7
12

More than 3 years have passed since last update.

ElectronとC++開発環境

Last updated at Posted at 2019-07-01

screen

19/07/01 Qiitaに画像ファイルがアップロードしにくい(やたら時間がかかってる)ので、あとでアップロードします。

今回のコンセプト

  • C++部分はElectronと連動しながらVisual Studio 2017でデバッグする。(C++11に対応していたら別バージョンでも使えるらしい)
  • node.jsはnodist仮想環境を使う(node.jsのバージョンが合うなら他の方法でも可能)
  • ビルド時にpython2.7使うのでAnacondaの仮想環境を使う(python2.7が動けば他の方法でも可)
  • node.jsパッケージはプロジェクトディレクトリのnode_modulesに保存して、そこから使う。
  • electron-rebuildは使わずnode-gypを使う。
  • Electronは5.0.5(新しいバージョンでやってみたいだけ)
  • 作りやすく、やり直しやすい環境構築を目指す。

開発環境

  • Windows 10 (64bit)
  • Visual Studio 2017
  • nodist : node.js環境作成
  • Anaconda : 一部python2.7バージョンを使うため

C++で開発する2種類の方法

native addon

node-gypを使ってC++をビルド。こちらを使う。

ffi

npm install ffiでインストールする方法。
この方法は、かなり制限(WinではElectronがバージョン3(nodeのバージョンのため)までしか対応してないとか、エラー地獄にあったりとか)があるので今回は使用しない。

nodistの設定

今回はElectron5.0.5を使うのでnode.js12以上が必要です。
とりあえず以下を実行して使いたいバージョンを用意。
Electronに必要な対応するnode.jsのバージョンはRelease noteに書いてあります。

rem 使用可能なnodeバージョン一覧
nodist dist
rem 使いやすそうなnode.jsのバージョンを選択してダウンロード
nodist + 12.4.0
rem ダウンロード済みの中で使用したいバージョンを指定
nodist use 12.4.0
rem 恒久的に今後同じバージョンを指定する場合はglobalで設定する
nodist global 12.4.0

Anacondaの設定

node-gypelectron-rebuildとかのライブラリでpython2.7を使うのでAnacondaにインストール

rem py27という名前で作成
conda create -n py27 python=2.7

プロジェクトの作成

undefined

普通にフォルダ作ってるだけです。

rem 例としてexampleという名前
mkdir examples
cd examples

プロジェクト作成

package.json作成

rem conda でpython27に変更
activate py27
rem nodistでnode.jsのバージョンを指定
nodist use 12.4.0
rem node初期化
rem 対話型で内容を設定
npm init

Electronとnode-gypをインストール

rem プロジェクトに保存してそこから実行する予定
npm install --save-dev electron@5.0.5
npm install --save-dev node-gyp@5.0.1

なんかエラー出たときは、package-lock.jsonを削除するとうまくいくかも

ファイルを用意

Hello Worldします。

node/test/addons/hello-world at master · nodejs/node · GitHub

スクリプトはこちらを参考にしました。

node-gypまたはnanを使ってnative addonを作る方法 - DJ lemon-Sour's diary (prod.hisasann)

HTML

ファイル名はindex.html

index.html
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>Example</title></head>
<body>
<div id='test'></div>
<button onclick="testFunc()">test button</button>
<script>
    function testFunc(){
        var remote = require('electron').remote;
        var testC = require('./build/Debug/testFunction');
        document.getElementById('test').innerText = "hello " + testC.hello();
    }
</script>
</body>
</html>

Electron用JS

ファイル名はindex.js

index.js
"use strict";
const electron = require("electron");
const app = electron.app;
const BrowserWindow = electron.BrowserWindow;
let mainWindow;

// 閉じたときのイベント
app.on('window-all-closed', function() {
  if (process.platform != 'darwin') {
    app.quit();
  }
});

// 初期化後
app.on('ready', function() {
  mainWindow = new BrowserWindow({
      width: 800, height: 600,
      webPreferences: {
          // Electron5以降ではこれがFalseになっていて、index.html側でrequireが使えないのでTrueにする(後述)
        nodeIntegration: true
  }
  });
  mainWindow.loadURL('file://' + __dirname + '/index.html');
  mainWindow.on('closed', function() {
    mainWindow = null;
  });
});

注意

今回は簡単に説明したいのでnodeIntegrationという値をtrueにしてますが、セキュリティ的に宜しく無いらしいので、適当に変更してください。

Electron Webviewのセキュリティで注意すべきこと - Qiita

package.json

package.jsonは先の初期化時に生成されているはずですが、"main": "index.js",となっていない場合(index.jsがメインファイルでない場合)は、そのように直しておく。

binding.gyp

node-gypが使用するビルド用の設定ファイル。
ファイル名はbinding.gypで固定

binding.gyp
{
  "targets": [
    {
      "target_name": "testFunction",
      "sources": [
        "test.cc"
      ]
    },
  ]
}

test.cc

test.cc
#include <node.h>
#include <v8.h>

void Method(const v8::FunctionCallbackInfo<v8::Value>& args) {
  v8::Isolate* isolate = args.GetIsolate();
  v8::HandleScope scope(isolate);
  args.GetReturnValue().Set(v8::String::NewFromUtf8(isolate, "world"));
}

void init(v8::Local<v8::Object> exports) {
  NODE_SET_METHOD(exports, "hello", Method);
}

NODE_MODULE(binding, init);

ビルド

ファイルができたらビルドしてみる。

Using Native Node Modules | Electron

electron-rebuildを使う方法もあるが、環境によってはうまく使いたいnode-gypのバージョンで使えなかったのでnode-gypでビルドする。

rem conda でpython27に変更
activate py27
rem nodistでnode.jsのバージョンを指定
nodist use 12.4.0
rem プロジェクトディレクトリに保存したnode_modules内のnode-gypを使ってビルド
.\node_modules\.bin\node-gyp.cmd rebuild --target=5.0.5 --arch=x64 --msvs_version=2017 --dist-url=https://electronjs.org/headers --debug

引数は以下

引数 内容
--target 5.0.5 Electronのバージョン
--arch=x64 x64 32bitか64bitか
--msvs_version 2017 Visual Studioのバージョン
--dist-url https://electronjs.org/headers この引数を加えることでElectronのビルドであることをnode-gypに伝える
--debug デバッグでビルド

引数一覧

実行

以下で実行。
ウィンドウが表示されて、ボタンを押したらHelloWorldが表示されればOK

.\node_modules\.bin\electron .

デバッグ

Visual Studio でデバッグしたいのでデバッグ用のプロジェクトを新たに作成します。

Visual Studio 2017で新しく「空のプロジェクト」を作成します。

対象のファイルを追加

プロジェクト名を右クリック->追加->既存の項目(G)...を選択して、デバッグの対象にしたいC++ファイルtest.ccを選択して追加。

追加されたファイルを右クリックしてプロパティを開く。

構成プロパティ->全般->ビルドから除外

を「はい」に設定。

デバッグ用のコマンドを設定

プロジェクトのプロパティ->構成プロパティ->デバッグ->コマンド

$(ProjectDir)..\..\node_modules\.bin\electron.cmd

同じく、コマンド引数

$(ProjectDir)..\..\.

に設定。

実行

設定後、普通にデバッグ->デバッグの開始を選択か、「ローカル Windows デバッガー」ボタンをクリック

アタッチ

デバッグ->プロセスにアタッチを選択して、electronという項目を探して、「タイトル」が空白のものを選択してアタッチする。(2個項目があるが、恐らくUIDが後の方だと思うが、シフトキーを押しながら複数選択のほうが確実かも)

ソリューションエクスプローラーのtestFunction/test.ccMethod関数のどこかにブレークポイントを設定して、Electron上のボタンを押すと、そのブレークポイントで停止します。これでデバッグができるようになりました。

アタッチについて

デバッグ実行ごとに上記アタッチの作業が必要になる。
node_modules\electron\dist\electron.exeをデバッグ時に自動的にアタッチできればもう少し楽できるかも。

その他設定

絶対ではないけど、やっておくと便利程度

デバッグ時にビルドも

今回のデバッグの設定はビルドをしていない。
ビルドもしておきたい場合は以下のようなバッチファイルをbuild.cmdという名前で用意して、

cd %~dp0
call activate py27
call nodist use 12.4.0
node_modules\.bin\node-gyp.cmd rebuild --target=5.0.5 --arch=x64 --msvs_version=2017 --dist-url=https://electronjs.org/headers --debug

ビルド前コマンドに以下のような内容を書いておけばビルドもされる。

..\..\build.cmd

説明

Electronとnode.jsとNODE_MODULE_VERSIONについて

Electronの指定をしないで普通のnode.jsでnode-gypを使ってビルドすると、NODE_MODULE_VERSIONが違う旨のエラーが表示される。
NODE_MODULE_VERSIONはABI(アプリケーションバイナリインタフェース)のバージョン番号で、普通のnode.jsとelectronと違うものが振られており、たとえ同じnode.jsとnpmのバージョンを使用してnode-gypでビルドしても上手く動作してくれません。(どこかにコレではないリストでElectronも含めたNODE_MODULE_VERSION一覧表があったはずだがURLを忘れた)

Electron から native module を使うときの NODE_MODULE_VERSION のエラー - 理系学生日記

参考

Using Native Node Modules | Electron

リリース一覧 | Node.js

Electron から native module を使うときの NODE_MODULE_VERSION のエラー - 理系学生日記

その他参考

Electronアプリを公開するまでにやったことノウハウまとめ - Qiita

とはいえ

デバッグ毎にアタッチするのはめんどくさいので、C++側はCLIとかで別途デバッグして、UI部分との結合用に使う程度が良いかも。

7
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
12