NimではじめてのGUI


Nim言語の利用の幅を広げるため、GUIアプリケーションを作成してみます。

なぜNim

ネーミング、HPの雰囲気、言語記述などが全体的に好き。
Go、Rustなどもちょこちょこ触りましたが、このへんの比較記事なども含めてNimいいなーと思っています。

Nimを実行するまで

Windows:10
nim:0.18.0
MinGW:6.3.0

ここまでは通常のNimの開発環境です。こちらのページに従って簡単に構成できます。
https://nim-lang.org/install_windows.html

GUIを作成する環境

使用するライブラリ:IUP

NimでGUIを作成するのには、IUPというGUIライブラリを使用します。

このIUPはNimに限ったGUIライブラリではなく、もともとLuaなど、Cを中心としたビルド環境でマルチプラットフォームでネイティブGUIを開発するためのライブラリのようです。

一度Nimをビルドするとわかりますが、Cにトランスパイル(と言っていいかな)されてからビルドされるので、IUPが使用できるというわけですね。

※もっと詳しい人、教えてください。。。

IUPをとってくる

次の場所にIUPのライブラリがあります。
https://sourceforge.net/projects/iup/files/

この時点での最新バージョン、3.24を選択します。

Windows64bit + MinGWに該当するIUPのライブラリをダウンロードします。
https://sourceforge.net/projects/iup/files/3.24/Windows%20Libraries/Static/iup-3.24_Win64_mingw4_lib.zip/download

ダウンロードしたZIPを解凍すると、次のような中身になっています。

.aファイルはリンカが使用するバイナリなので、これをMinGW(gcc)に渡せば、使用できそうですね。

NimからIUPを呼び出せるようにする

Nimのコード内でIUPのライブラリを呼び出す必要があります。
それには、公式のIUPラッパーがありますので、それを使用します。

READMEに従って、次のコマンドでインストールします。

$ nimble install iup

これで環境の準備が完了しました。いよいよプログラムを作ります。

IUPのプログラム

同じくIUPラッパーのGithubにサンプルがありますので、それを使ってみます。

menu.nim
import iup

discard iup.open(nil, nil)

var fileItemLoad = iup.item("Load", "")
var fileItemSave = iup.item("Save", "")
var fileItemClose = iup.item("Close", "")

var fileMenu = iup.menu(fileItemLoad, fileItemSave, fileItemClose, nil)
var mainMenu = iup.menu(iup.subMenu("File", fileMenu), nil)

discard iup.setHandle("mainMenu", mainMenu)

var dlg = iup.dialog(nil)
iup.setAttribute(dlg, "TITLE", "iupTabs")
iup.setAttribute(dlg, "SIZE", "200x100")
iup.setAttribute(dlg, "MENU", "mainMenu")

discard iup.showXY(dlg, IUP_CENTER, IUP_CENTER)
discard iup.mainLoop()

iup.close()

IUPのライブラリを今回はプロジェクトフォルダのiupフォルダに放り込みます。
次のような構成になります。

では、ビルドをしてみましょう。

$ nim c -d:release --dynlibOverride:iup -L:iup/libiup.a -L:iup/libiupcd.a -L:iup/libiupim.a -L:-lgdi32 -L:-luser32 -L:-lcomdlg32 -L:-lcomctl32 -L:-lole32 -L:-luuid menu.nim

これはNimからCにトランスパイルされたあと、次のようなコンパイルが内部で行われています。

gcc.exe -o C:\○○○\menu.exe  C:\○○○\nimcache\menu.o C:\○○○\nimcache\stdlib_system.o C:\○○○\nimcache\stdlib_iup.o  iup/libiup.a iup/libiupcd.a iup/libiupim.a -lgdi32 -luser32 -lcomdlg32 -lcomctl32 -lole32 -luuid

32とついてるのは全部Win32のライブラリですね。からっきしですが・・・

gdi32: 画面描画
user32: ユーザ周り?
comdlg32: コモンダイアログ
comctl32: コモンコントロール(ボタンとか?)
ole32: リンカ?( https://ja.wikipedia.org/wiki/Object_Linking_and_Embedding
uuid: UUID(何に使ってるんでしょ?)

※詳しい人、教えてください。。。

とりあえずこれでexeができると思いますので、実行してみましょう。

:*:・。,☆゚'・:*:・。,ヽ(・NIM・)人(・IUP・)ノ ,。・:*:・゚'☆,。・:*:

やりましたね!

今後やりたいこと

  • nim.cfgを活用してコマンドを短縮すること
  • IUPライブラリをプロジェクトフォルダではなくMinGW側に移動すること(ビルド環境によって異なるので・・・)
  • その他のプラットフォームでのビルド

Nimいかんせん実際のビルド周りの情報が全然見つからなくて辛いので、皆さんもぜひ情報共有してください!

そもそものCビルドについても勉強しないといけないですが。。。orz