JuliaでQtを使ってみる?


とりあえず

なにやらJuliaという言語が面白いらしいというのをつい最近知った。
こーゆーのはとりあえず1回ぐらいHello Worldを書いてみる程度に興味はあるんだけど、なにげなく"Julia Qt"でググってみたらちゃんとJuliaからQtを使えるようにしてくれているのを発見したので、とりあえず動かしてみた。

Juliaのインストール

なにがともあれJulia本体をインストールしておく必要がある。
Ubuntu使いとかなら多分フツーにapt installすればいい(?)んだと思うんだけど、手元の環境がGentooなのでとりあえずemergeを試みてみる。
これ書いてる時点でVer. 1.1.0のebuildがアップストリームに入ってるんだけど、まだstableではないっぽいのでとりあえず以下の設定をした。

/etc/portage/package.accept_keywords/julia.accept_keywords
>=dev-libs/openspecfun-0.5.1 ~amd64
>=sci-libs/blas-reference-20161223 ~amd64
>=virtual/blas-3.7 ~amd64
>=sci-libs/openlibm-0.5.4 ~amd64
>=sci-libs/spqr-1.3.1 ~amd64
>=dev-lang/julia-1.1.0 ~amd64

"emerge -p"した段階では sci-libs/spqr は何も言われなかったんだけど、どうもビルドで引っかかるので~amd64を設定しといた。

とりあえずこれでemergeしてみる。

% emerge julia

まぁ、Gentooはこれだけで必要なパッケージを全てビルド&インストールしてくれるからあとは結果を御覧じろって感じだろうか。

QML.jlのインストール

Juliaはその環境から追加パッケージの管理ができるようになってるんだけど、QML.jlのインストールにはまずjlqmlをビルドしておく必要があるらしい。そしてjlqmlのビルドにはlibcxxwrap-juliaが必要っぽい。

というコトでまずはlibcxxwrap-juliaをビルドしておく。(以下、ホームディレクトリの直下で作業している前提で書く)

$ git clone https://github.com/JuliaInterop/libcxxwrap-julia
$ mkdir libcxxwrap-julia-build
$ cd libcxxwrap-julia-build
$ cmake ../libcxxwrap-julia
$ make

一旦ホームディレクトリに戻って、今度はjlqmlをビルドする。

$ git clone https://github.com/barche/jlqml
$ mkdir jlqml-build
$ cd jlqml-build
$ cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=/home/user_name/libcxxwrap-julia-build ../jlqml
$ make

ここまで準備できたらおもむろにjuliaを起動してみる。

helicalgear@pcd01010 ~ $ julia
               _
   _       _ _(_)_     |  Documentation: https://docs.julialang.org
  (_)     | (_) (_)    |
   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 1.1.0 (2019-02-25)
 _/ |\__'_|_|_|\__'_|  |  Commit 32dca98* (20 days old master)
|__/                   |

julia> 

"JLQML_DIR"という環境変数に上でビルドしたjlqmlのPATHを指定する。絶対PATHにしておかないと後でエラーが出るので注意が必要。

julia> ENV["JLQML_DIR"] = "/home/user_name/jlqml-build"

"]"を入力するとパッケージモード(?)になるので、以下のように入力する。

(v1.1) pkg> add QML#master

あとはおまかせしておけば必要なパッケージを全てインストールしてくれる。

まずは使ってみる。

とりあえずは適当にHello Worldなqmlファイルを用意してみる。

main.qml
import QtQuick 2.0
import QtQuick.Controls 1.0

ApplicationWindow {
    title: "Hello from Julia"
    width: 480
    height: 640
    visible: true
}

ファイルを用意したらjuliaを起動する。まずはQML.jlを呼び出しておく。

julia> using QML

あとは以下のようにして呼び出すととりあえず動く。

julia> load("/home/user_name/main.qml")
julia> exec()

load()した段階でウインドウは表示されるんだけど、実際の中身は描画されない。
qml自体はexec()を呼ばないと実行されないらしい。
というワケで上の2つを実行すると下のようになる。

もう少しちゃんと使おう。

まずJuliaの方から。
とりあえず冒頭の"using QML"でQML.jlを使うことを宣言する。
Juliaでの基本的な処理を組み立てた後"@qmlfunction"でQML側から使うfunctionを羅列する。
その他、QMLファイルを呼び出す時に渡したいプロパティ値についてはload()で引き渡すことができる。

sample.jl
using QML

function hogehoge()
    return "HogeHoge"
end

function fugafuga()
    return "FugaFuga"
end

@qmlfunction hogehoge fugafuga

load("/path/to/qml_file/sample.qml", property1="bokeboke", property2="pakapaka")

exec()

呼び出されるQMLファイル側は、"org.julialang 1.0"をインポートする事で上の@qmlfunctionで指定した機能を"Julia.xxxx()"の形で呼び出せるようになる。
プロパティについては特段の操作は不要っぽい(QML側で渡されるプロパティを定義しておく必要はないらしい)けど、それはそれでいいのかな?
QMLファイル書いてる時にどんなプロパティがあるのかいちいちjlファイルを見ないと判らなくなりそうだけど・
・・まぁ、自分でちゃんとコメント書くなりして工夫するしかないのかな。

sample.qml
import QtQuick 2.0
import QtQuick.Controls 1.0
import org.julialang 1.0

ApplicationWindow {
    title: "Hello from Julia"
    width: 480
    height: 640
    visible: true

    Column {
        Text {
            text: Julia.hogehoge()
        }

        Text {
            text: Julia.fugafuga()
        }

        Text {
            text: property1
        }

        Text {
            text: property2
        }
    }
}

まぁ、こんな感じでバックエンドにいるjlファイルと値をやりとりしながらQML側でインターフェイスを作るって感じになるらしい。

パッケージ付属のサンプルの動かし方

QML.jlにはサンプルが付属していて("~/.julia/packages/QML/HASH_VALUE?/example/"辺りにある)、以下の手順で動かすとサンプルを片っぱしから動かしてみてくれる。
ただし、一部サンプルは追加のパッケージが必要になるので、「なんかが無いから動かないよ」みたいなことを言われたら"]"を入力してパッケージモードにした後に"add hogehoge"ってやってあげると動くようになる。

julia> using Pkg
julia> include(joinpath(Pkg.dir("QML"), "example", "runexamples.jl"))

というコトで・・・

そもそもまだちゃんとJuliaのコードを書けないので(だったら何故この記事を書いた!?)サンプルがかなりいい加減なんだけど、とりあえずJuliaからもQt(QML)が使えるよーってことでなんとなく紹介してみた。
最近ほとんどコード書けてないので、ちゃんと時間を取ってはりきらない程度に頑張ってみよう。