インストールが簡単なRuby用のGUIライブラリlibuiのバインディングを作った話


追記

現在、LibUI上に構築された使いやすいDSL、glimmer-dsl-libui がAndy Maleh氏によって開発されました。素のLibUIで使いにくいところが大幅に改良されています。おすすめです。

はじめに

こんにちは。

今日はRuby3.0がリリースされる日です。
先日libuiというRubyでGUIを作れるGemをリリースしました。
( libui のバインディングです)
まだまだ足りない部分は多いかと思いますが記事にします。

Windows Mac Linux

背景とモチベーション

 これまでにもRubyのGUIライブラリは多数作られてきました。Ruby/TkRuby/Gtk、一世を風靡したShoes、Qt, FXRuby、ほかにもたくさん。

 しかし、Windows環境で手軽にGUIアプリケーションを作る方法が少ないという状況は続いていました。Ruby/GtkやRuby/Tkを利用する場合、TkやGTKといったツールキットのインストールが必要です。これは、初心者にとって障壁になります。また、ベテランの方でも、ユーティリティにさくっとGUIを追加して配布したいことはあると思います。この問題を解決するために、libuiというポータブルなGUIライブラリのバインディングを作成しました。

 libuiは2020/12/25時点で、Ruby界で最もインストールが簡単なGUIライブラリだと思います(たぶんね)。

libuiとは

 libuiは非常に軽量なC言語で書かれたマルチプラットフォームなGUIツールです。Rubyバインディングは、バージョン4.1に対応しています。

インストール

gem install libui

簡単なつかい方

下記に簡単な使用例を示します。

require 'libui'

UI = LibUI

UI.init

# ウィンドウを作成
main_window = UI.new_window('hello world', 300, 50, 1)
# ×ボタンでウィンドウを消せるようにする
UI.window_on_closing(main_window) do
  puts 'Bye Bye'
  UI.control_destroy(main_window)
  UI.quit
  0
end

# 配置用のボックス
hbox = UI.new_horizontal_box
# ボックスをウィンドウに追加
UI.window_set_child(main_window, hbox)

# 入力欄の作成
entry = UI.new_entry
# 文字が入力されたターミナルに表示
UI.entry_on_changed(entry) do
  puts UI.entry_text(entry).to_s
  $stdout.flush # リアルタイムにターミナルに表示
end
# ボックスに追加
UI.box_append(hbox, entry, 1)

# ボタン
button = UI.new_button('Button')
# ボタンが押されたら、ダイアログを出す
UI.button_on_clicked(button) do
  text = UI.entry_text(entry).to_s
  UI.msg_box(main_window, '入力した文字は次の通りです', text)
  0
end
# ボックスに追加
UI.box_append(hbox, button, 0)

# ウインドウを表示
UI.control_show(main_window)
UI.main
UI.quit

(irbやpryだとうまく実行できないのでご注意ください)

もう少し詳しいつかい方を知りたい方は、リポジトリのExamplesを見てください。

記法の一般的なルール

Cで書かれたオリジナルのlibuiと比較して、

  • メソッド名はsnake_caseです。
  • 最後の引数がnilの場合、省略できます。
  • ブロックをコールバックとして渡すことができます。
    • ブロック内で明示的に0を返してください。
    • ブロックはProcオブジェクトに変換され、最後の引数に追加されます。
    • その場合でも、最後の引数nilを省略できます。

オブジェクト指向じゃないの?

  • 現時点では、オブジェクト指向ではありません。
    • 中途半端なオブジェクト指向アプローチを提供する代わりに、そのままにしています
    • 将来的にオブジェクト指向にしていくかは現時点では未定です。

既存のlibuiバインディングとの比較

libuiには、すでにRubyのバインディングが存在します。

 しかし、このパッケージはインストールが面倒という弱点があります。libuiはこの点を解消しています。

  • C言語の関数の呼び出しに、Ruby標準ライブラリのfiddleを用いて行っています。(追加のライブラリは不要です)
  • libuiの共有ライブラリをGemの中に梱包しています。(libuiのインストールは不要です)
    • libui.so, libui.dylib, libui.dll です。
    • Gemのサイズを心配する人がいるかもしれませんがご安心ください。 全て合わせてもファイルサイズはたったの1.4MBです。Ruby/Tkと比較してもかなり軽量です。Windowsしか使わないという方は、あとからlibui.so, libui.dylibを削除しても大丈夫です。この場合、libui.dll は269Kしかありません。とても軽量です。
  • libui-rubyよりもRubyらしい記法を実現しています。特にブロック記法を用いたコールバックに対応しています。

OCRAを使って実行ファイル(EXE)を作る方法

次の3つのdllを指定する必要があります。また、念の為にfiddleを確実に含めるようにしておきます

ocra examples\control_gallery.rb        ^
  --dll ruby_builtin_dlls\libssp-0.dll  ^
  --dll ruby_builtin_dlls\libgmp-10.dll ^
  --dll ruby_builtin_dlls\libffi-7.dll  ^
  --gem-all=fiddle                      

さらに、必要に応じて次のようなオプションを追加します。詳しくはOCRAのマニュアルをご覧ください。

  --window                              ^
  --add-all-core                        ^
  --chdir-first                         ^
  --icon assets\app.ico                 ^
  --verbose                             ^
  --output out\gallery.exe

おまけ 非同期処理しなきゃならないときにはdrubyというのがあります

 RubyでGUIを伴うデスクトップアプリケーションを作るというのは、Shoesの一時的なブームを除いて、あまり流行しない印象があります。その理由の一つは、GUI側と、Rubyのロジックの非同期処理が面倒くさいからだと思います。この場合、drubyを利用するのが一つの解決策になることがあります。参考まで。