貝柱が何かをする所

貝柱が何かをする所です、C++/Perl/その他諸々

Visual Studio 2017でNanaを試す

長らく記事を書いていなかった。サボりすぎだ。
やはり良いコードを書く人というのは、記事を多く投稿し技術を発信している。自分も頑張ろう。

Nanaとは?

C++GUIを書こうと思ったとき、幾つかの選択肢が存在する。
例えば、Qt、wxWidgetなどの名前が挙がるが、今日紹介するのは日本ではあまり記事を見かけない、Nanaというライブラリだ。
Nana C++ Library - a modern C++ GUI library
Nanaは、WindowsLinuxで動くクロスコンパイル可能なGUIライブラリだ。
最大の特徴は、

GUI programming in modern C++ style.

と、モダンなC++コードでGUIを書くことを意識されたライブラリであることだ。
非常に興味深いので、環境構築から簡単なコードのコンパイルまでを記事に残しておこうと思う。
環境は、Windows 7 SP1 32bit、そしてVisual Studio Community 2017だ。
なお、Macは"experimental"であるとの事だ。

リポジトリのcloneとビルド

Nanaは現代の流れに乗り、例外なくオープンソースだ。
GitHub - cnjinhao/nana: a modern C++ GUI library

githubから最新のソースをcloneしてくる。

$ git clone https://github.com/cnjinhao/nana.git nana

次に、includeフォルダを環境変数に登録する。変数名は好きなので良い。
例えば筆者はNANA_INCLUDEなどとした。nanaフォルダ直下のincludeを登録する。

NANA_INCLUDE=C:\nana\include

そしてbuildフォルダに存在するvc2015のnana.slnをVS2017で開く。
その際、何も意識せずVS2017へアップコンバートすれば良い。
プロジェクトのプロパティからインクルードパスを追加する。

追加のインクルードパス
>$(NANA_INCLUDE)

筆者の環境ではVS2017ではWindows 10のSDKしか入れてなかったので、
必要に応じて、構成プロパティ>全般 から「Windows SDKバージョン」を8から10に変えておく。

次にそのままではビルド後問題が発生するので、include\nana\c++defines.hppを以下のように改変する

#if (_MSC_VER >= 1900) // <= _MSC_VER == 1900をこのように
	// google: break any code that tries to use codecvt<char16_t> or codecvt<char32_t>.
	// google: It appears the C++ libs haven't been compiled with native char16_t/char32_t support.
	// google: Those definitions are for codecvt<wchar_t>::id, codecvt<unsigned short>::id and codecvt<char>::id respectively.
	// However, the codecvt<char16_t>::id and codecvt<char32_t>::id definitions aren't there, and indeed, if you look at locale0.cpp in the CRT source code you'll see they're not defined at all.
	// google: That's a known issue, tracked by an active bug (DevDiv#1060849). We were able to update the STL's headers in response to char16_t/char32_t, but we still need to update the separately compiled sources.
	#define STD_CODECVT_NOT_SUPPORTED
#endif // _MSC_VER == 1900


後はそのままDebugモード、Releaseモードでそれぞれビルドする。
問題なければ、nana\build\bin直下に2つのlibが生成されるはずだ。
f:id:shellbasira:20170502001108p:plain

これでライブラリのビルドは完了した。
このままでも使えるが、例によって環境変数を登録すると楽なので筆者は環境変数を登録した。
環境変数を使わない場合は以降で説明する追加のライブラリディレクトリに、binのパスを指定する。

NANA_LIB=C:\nana\build\bin

プロジェクトの作成

Visual Studioをたちあげる。
プロジェクトの新規作成から、「Visual C++ > Win32 コンソールアプリケーション」を選択する。
プロジェクトの作成ウィザードで、必ず「空のプロジェクト」にチェックを入れておくこと。
f:id:shellbasira:20170502002002p:plain

ソースファイルに適当にファイルを追加したら、プロジェクトの設定を行う。
結構めんどくさいので、マクロか何かで定義しても良いかもしれない。

  • [全ての構成]で行う

C/C++ > 全般
追加のインクルードパス:$(NANA_INCLUDE)
リンカー > 全般
追加のライブラリディレクトリ:$(NANA_LIB)

  • C/C++ > コード生成

[Debug]
ランタイムライブラリ > マルチスレッドデバッグ(/MTd)
[Release]
ランタイムライブラリ > マルチスレッド (/MT)

  • リンカー > 入力

[Debug]
追加の依存ファイル > nana_v141_Debug_x86.lib
[Release]
追加の依存ファイル > nana_v141_Release_x86.lib

後は公式に載っているサンプルをビルドしてみよう。

#include <nana/gui.hpp>
#include <nana/gui/widgets/label.hpp>
#include <nana/gui/widgets/button.hpp>

int main()
{
	using namespace nana;

	//Define a form.
	form fm;

	//Define a label and display a text.
	label lab{ fm, "Hello, <bold blue size=16>Nana C++ Library</>" };
	lab.format(true);

	//Define a button and answer the click event.
	button btn{ fm, "Quit" };
	btn.events().click([&fm] {
		fm.close();
	});

	//Layout management
	fm.div("vert <><<><weight=80% text><>><><weight=24<><button><>><>");
	fm["text"] << lab;
	fm["button"] << btn;
	fm.collocate();

	//Show the form
	fm.show();

	//Start to event loop process, it blocks until the form is closed.
	exec();
}

以下のウィンドウが出てくるはずだ。
f:id:shellbasira:20170502004703p:plain

環境構築の記事を書いただけで良い時間になり疲れてしまった

実はまだ深く触れていない。なのでまだこのライブラリのモダンな部分には少ししか触れていない。
これから触ってリポートして行きたいと思う。
どうやらマウスクリックなどのイベントにラムダを流し込む事なども出来るようだ。
また、列挙子が必要な時は、基本的にscoped enumを使っているのも興味深い。

どこまでこのライブラリがモダンに染められているのか、業務の合間に機を見て触ってみようと思う。