2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

シンプルにNimでElectronをつかってみる

Last updated at Posted at 2022-02-06

サンプル

たのしくなって、基本的なところを実験してみました。

下記に、そのときのサンプルをあげました。

クイックスタートから、プロセス間通信、ファイルの読み込みなどのサンプルですので、これだけわかれば、一通りのことは使えるようになるのではないでしょうか。

下記は、quickstart の説明になります。

クイックスタート

OSは、Linuxを使っています。

前提条件として、下記のツールを入れておいてください。

  • nim
  • npm
  • node.js

話をもどします。

入っていたら、早速はじめましょう。

まず、テスト用のディレクトリをつくって、npm initしましょう。

% mkdir nim-electron-test
% cd nim-electron-test
% npm init -y

package.jsonがつくられたはずです。

つぎに、electronをインストールしましょう。

% npm i -D electron

同じディレクトリに、index.nimという名前で、下記のコードを書いて保存ください。

index.nim
import jsffi

let electron = require("electron")
let app = electron.app

app.whenReady().then(proc() = 
  (jsnew electron.BrowserWindow()).loadFile("index.html")
)

app.on("window-all-closed", proc() =
  if require("process").platform.to(cstring) != "darwin":
    app.quit()
)

require は、jsffi モジュールに入っている、javascriptのライブラリを読み込むもののようです。

参考:( https://nim-lang.org/docs/jsffi.html )

次に、index.htmlに、適当になにか書いてください。
ここでは面倒なのでタグなど書かず、以下のように書いたことにします。

index.html
こんにちわ

保存したら、コマンドラインで以下を実行します。

% nim js index.nim

エラーが出ていなければ、index.jsというファイルができています。

できていたら、下記を実行してください。

% npx electron .

一番最後に、ピリオド(.)の入力を忘れないようにしてください。

問題なければ、新しいwindowが開いて、「こんにちわ」と表示したと思います。

さて次にwindowの大きさを変えてみます。
ソースコード(index.nim)の一部に、下記のコードがあります。

(jsnew electron.BrowserWindow()).loadFile("index.html")

ここの「jsnew electron.BrowserWindow()」の()内に、大きさの指定を書きます。
Nimなので、インデントは忘れないように。

(jsnew electron.BrowserWindow(
  JsObject{
    width: 100,
    height: 200
  }  
)).loadFile("index.html")

保存したら、前述したように、nim js ...して、npx ....を実行してみてください。
小さくなったwindowが開きましたか?

おまけで、preloadも記述します。
preloadがなにかは、ご自身でしらべてください。

index.nimの、大きさ指定したコードにつけたします。

(jsnew electron.BrowserWindow(
  JsObject{
    width: 100,
    height: 200,
    webPreferences: JsObject{
        preload: "preload.js"
    }
  }  
)).loadFile("index.html")

preload.js は、nimのコードで記述したければ、別途コンパイルが必要になります。
追記ですが、preload.jsは、フルパスで指定する必要があります。

% nim js preload.nim

index.htmlから外部ファイルで読み込みたいソースも、別途コンパイルが必要です。

% nim js renderer.nim

その場合、index.htmlには、以下のように記述が必要でしょう。

index.html
<script src="renderer.js"></script>

以上です。

閑話休題

よく、nim+electronで、参考にするのは、下記のサイト?だと思います。

これ、このままだと、electronが起動しません。
package.json内の、electronのバージョンが古すぎて、gconfなんたらがないと文句いわれて落ちます。
調べると、昔のchromeを入れてると自動でインストールされたらしいのですが、今は使わないとのこと。
なので、package.jsonの下記の部分を削除して、(もしくはバージョンを書き換えて)、最新のelectronをインストール必要があります。

package.json
"devDependencies": {
    "electron": "~1.6.2"
  }

また、main.nimも、なぜか、app.nimで作成されたアプリとsocket通信するサンプルになっています。
なので、このままだと、落ちます。
socket通信している部分は削除が必要です。

main.nim
var client = jsnew net.createConnection(JsObject{ port: 1234 }, proc () =
  console.log("Connected to server!")
)
main.nim
 client.write "Hello, world\r\n"

上記2箇所は不要です。

また、不要なモジュールをロードする必要がないので消しましょう。

main.nim
{.emit: """
const electron = require('electron')
const path = require('path')
const url = require('url')
const net = require('net');
""".}

ここでいえば、一番下のnetは不要です。

これで、上記のサンプルは動作します。

さて、emitですが……(これは、コンパイル時に指定した言語を実行するものらしいです)

jsffiのドキュメントを英語がわからないなりに、ながめていると、requireというプロシージャがあるではないですか。

なので、思い切って、このemitの部分は削除して、直接、requireでelectronをロードしてみたら、うまく動作しました。

最近のelectronだと、BrowserWindowは、loadURL ではなく、loadFileを使うようです。

そうなると、urlモジュールは不要です。consoleは、デバッグする必要がなければ不要でしょうし、そもそも、ふつうにechoでもいけました。(レンダラープロセスで動作するかは不明)

__dirnameや、pathは、お好みでどうぞ、だと思います。
たぶん、こんな感じ。

let dirname {.importc: "__dirname", nodecl.}:cstring
let path = require("path")

dirname ですが、nim はアンダーバーではじまる変数名は使えないので、はずしてあげなきゃいけないです。最初から、cstringにしておけば、dirname.to(cstring) としなくても良いようです。

使う場合は、loadFileの引数で下記のように利用しているようです。loadFromの前は省略。

loadFile(dirname & "/index.html")
# または、
loadFile(path.resolve(dirname, "index.html"))

次にprocessは、一回しか使わないので、

if require("process").platform.to(cstring) != "darwin":
  app.quit()

としています。

macで動作することを考慮しないのであれば、このif文は不要です。
蛇足ですが、macはwindowを閉じても、終了しない仕様なので、この判定をしています。

このように、できるかぎり削除していったら、最初の、main.nim ではなくて、index.nimのようになりました。

index.nimにしたのは、単に、npm init したときにできるpackage.jsonのデフォルトがmain.jsだからです。

ところで、自分で書いたコードなのですが、冷静になると、下記のコードはやりすぎ感はあります。

index.nim
app.whenReady().then(proc() = 
  (jsnew electron.BrowserWindow()).loadFile("index.html")
)

proc内は、下記のように分けたほうが使い勝手はよいでしょう。

index.nim
app.whenReady().then(proc() = 
  let win = jsnew electron.BrowserWindow()
  win.loadFile("index.html")
)

他に下記コードは必要か不要か、好みなのかは、意見がわかれるような気がします。

index.nim
win.on("closed", proc () =
  win = nil
)

公式のドキュメントの翻訳だと入れてはいないですね。

なんにせよ、nimで、electronを動かすメリットがどの程度あるのかわかりませんが、参考になれば幸いです。

2
1
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
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?