ホーム
C/C++チュートリアル
はじめの一歩
次のコードを、お好きなエディタで記述して、hello.c という名前でお好きな場所に保存してください。Windowsの場合は、C:¥msys64¥home¥ユーザー名
に保存するのが便利です。
hello.c
#include <gtk/gtk.h>
void activate();
int main(int argc, char **argv)
{
GtkApplication *app;
int status;
app = gtk_application_new ("jp.vivacocoa.hello", 0 );
/* G_APPLICATION_FLAGS_NONE == 0 */
g_signal_connect (app, "activate",
G_CALLBACK(activate), NULL);
status = g_application_run (G_APPLICATION(app), argc, argv );
g_object_unref (app);
return status;
}
void activate(GtkApplication *app, gpointer data)
{
GtkWidget *window;
window =
gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW(window), "Hello" );
gtk_window_set_default_size (GTK_WINDOW(window), 300, 200 );
gtk_window_set_position (GTK_WINDOW(window), 1 );
/* GTK_WIN_POS_CENTER == 1 */
gtk_widget_show_all (window);
}
コンパイル
-
コードファイルの記述が終わりましたら、ソースコードを機械語に変える
コンパイルという作業が必要です。
-
ターミナルもしくはMSYS2を起動して、
hello.cを保存したディレクトリに移動してください。
-
Windowsの場合に、
C:¥msys64¥home¥ユーザー名
に保存した場合は、MSYS2 を起動した画面が、
hello.c を保存した場所になります。
- GTK3でコンパイルする場合は、次のコマンドを使います。
どのプラットフォームでも同じです
-
gcc hello.c `pkg-config --cflags --libs gtk+-3.0`
-
コンパイルに成功すると、macOSとLinuxでは a.out、Windowsでは a.exe
という実行ファイルが作成されます。
-
実行ファイルを特定の名前にしたい場合は、コンパイル時に -o オプションをつけて
次のようにします。
-
gcc hello.c `pkg-config --cflags --libs gtk+-3.0` -o Hello
-
macOSとLinuxでは Hello、Windowsでは Hello.exe
という実行ファイルが作成されます。
実行方法
// 実行方法
// macOS Linuxの場合
./a.out
./Hello
// Windowの場合
./a
./Hello
// ダブルクリックによる実行方法は後ほど説明します。
実行結果
-
ウィンドウを閉じるとアプリケーションは終了します。
-
ウィンドウのサイズを指定しなかった場合のデフォルトサイズは、横 200 ピクセル
縦 200 ピクセルになるみたいです。
-
ウインドウの位置を指定しなかった場合のデフォルトの位置は、
スクリーンの左上に表示されるみたいです。
コード説明
- #include <gtk/gtk.h>
gtk/gtk.hを読み込んでいます。このヘッダーファイルにはGTKとCの
関数、型、定数、マクロのほとんどが定義されてています。
- void activate();
GTK3のプロトタイプ(関数前方宣言)には引数は明記しなくても大丈夫みたいです。
- int main(int argc, char *argv[])
main関数の引数には、Cで定番となっている int argc とchar **argv が必須です。
- GtkApplication *app;
GtkApplicationはアプリケーションの起動、終了、イベントループなどを担当する
ウィジェットです。このウィジェットを使うようになったところがGTK2とGTK3の違いの
一つです。
- app = gtk_application_new ("jp.vivacocoa.hello", 0);
GtkApplicationを作っています。引数は次のとおりです。
- 第1引数にアプリケーションのID(識別子)を文字列で指定します。
この識別子は世界で一意の文字列でなければなりません。
通常は上記のようにURLを逆順に並べて、最後にアプリケーション名をつける方法が
使われます
- 第2引数にアプリケーションのニーズに合わせた定数を指定します。
特に指定するようなことがなければ、G_APPLICATION_FLAGS_NONEを指定します。
この定数には0が定義されていますので、今後このチュートリアルでは0を使用します
- g_signal_connect(app, "activate", G_CALLBACK(activate), NULL);
g_signal_connect関数で個別のウィジェットが発するイベント(event)
を関数や処理と結びつけます。イベントと結びつけられた関数や処理のことを
イベントハンドラー(event handler)と言います。引数は次のとおりです。
- 第1引数にイベントを発するウィジェットを指定します
- 第2引数にそのウィジェットが発するイベントの種類を文字列で記述します。
GtkApplicationの"activate"イベントは、
アプリケーションが開始された時に発せられます
- 第3引数にイベントと結びつける関数や処理をG_CALLBAKC( )マクロで囲んで
指定します。
- 第4引数にイベントハンドラーに第2引数として渡すウィジェットを指定します。
必要ないときはNULLと記述します。イベントハンドラーの第1引数にはイベントを発した
ウィジェットが渡されます
- status = g_application_run(G_APPLICATION(app), argc, argv);
g_application_run関数でアプリケーションを開始します。引数は次のとおりです。
-
第1引数にGtkApplicationの変数をG_APPLICATION( )マクロで囲んで指定します
- 第2引数にmain関数の第1引数を指定します。これによってアプリケーションで
コマンドライン引数が使えるようになります
- 第3引数にmain関数の第2引数を指定します。これによってアプリケーションで
コマンドライン引数が使えるようになります
アプリケーションを開始するとイベントループが始まります。
アプリケーションが終了するとどのような状態で終了したかを表す整数が返ります。
正常終了の場合は0が返されます。そしてその値をstatusに代入しています。
- g_object_unref(app);
g_object_unfef( )関数で引数の変数が使用していたメモリー部分を解放します。
- return status;
main関数は終了する時に何かの整数を返さなければなりません。正常終了した場合は0を
返すことになっています。
- void activate(GtkApplication *app, gpointer data)
GtkApplicationの"activate"とイベントと結びつけられたイベントハンドラーです。
引数は次のとおりです。
- 第1引数にGtkApplication型のポインターを受け取ります
- 第2引数にgpointerというGTKで汎用的に使えるポインターを受けます。
今回はこの引数には何も代入されていません
- GtkWidget * window;
GtkWidget型は、すべてのウィジェット(widget、GTK3のGUIパーツ)を表す型です。
多くのウィジェットの変数はまず、この型で定義して、実際に使う時に、
実際の型にキャスト(cast、変換)して使う方法をとります。
- gtk_application_window_new(app);
gtk_application_window_new( )関数でアプリケーションのウィンドウを作ります。
引数にはGtkApplicationのポインターを指定します。
- gtk_window_set_title(GTK_WINDOW(window), "Hello");
gtk_window_set_title( )関数でウィンドウのタイトルバーに表示される文字列を
設定します。引数は次のとおりです。
- 第1引数にウィンドウをGTK_WINDOW( )マクロで囲んで指定します。
一つのアプリケーションに一つのウィンドウとは限らないので指定しなければなりません
- 第2引数にタイトルバーに表示する文字列を指定します。
タイトルを設定しない場合は、実行ファイル名がウィンドウのタイトルになります
- gtk_window_set_default_size(GTK_WINDOW(window), 300, 200);
gtk_window_set_default_size( )関数でウィンドウのサイズを設定します。
引数は次のとおりです。
- 第1引数にGTK_WINDOW( )マクロで囲んでウィンドウを指定します
- 第2引数に横のサイズを指定します
- 第3引数に縦のサイズを指定します
サイズを設定しなかった場合は、
横200ピクセル縦200ピクセルの大きさになると思います。
- gtk_window_set_position(GTK_WINDOW(window), 1);
gtk_window_set_position( )関数でウィンドウが表示される位置を設定します。
引数は次のとおりです。
- 第1引数にウィンドウをGTK_WINDOW( )マクロで囲んで指定します
- 第2引数に位置を表す定数を指定します。GTK_WIN_POS_CENTERは
中央に表示する定数です。1が定義されていますので、今後このチュートリアルでは1を
使います。<>li>
ウィンドウの位置を設定しない場合は、多くの場合は左上に表示されます。Mintなどは
デフォルトで中央に表示されます。
- gtk_widget_show_all(window);
gtk_widget_show_all( )関数でウィンドウとその子ウィジェット
(そのウィンドウに所属しているウィジェット)を表示しています。
ウィンドウも含めてGTKのウィジェットは作っただけでは表示されません。
ダブルクリックで起動できるようにする
Windows
-
Windowsではアプリケーションをダブルクリックで起動するには、
そのアプリケーションにDLLライブラリというものを含めなければなりません。
-
今のところ、MSYS2でコンパイルした、GTKの実行ファイルに
DLLライブラリを含める方法を、私は見つけ出せていません。
-
しかし、Windows 10では、環境変数でDLLライブラリへのパスを通すことによって
擬似的にダブルクリックで起動することができるようになります。
-
まず、次のように -mwindows オプションをつけてコンパイルし直してください。
-
gcc hello.c `pkg-config --cflags --libs gtk+-3.0` -mwindows
-
-mwindows オプションをつけないと、ダブルクリックで起動した時に、
コマンドプロンプトも起動してしまいます。
-
そして環境変数に次のパスを追加してください。
-
C:¥msys64¥mingw64¥bin
-
Windows 10 を再起動すると、アプリケーションを
ダブルクリックで起動できるようになります。
-
なお、この方法でも、Windows XP や Windows 7 では、
ダブルクリックによる起動はできません。
macOS
-
ターミナルを起動して、hello.cpp を保存したディレクトリに移動し、次のコマンドを実行してください。
-
gcc hello.cpp `pkg-config --cflags --libs gtk+-3.0` -o hello
-
コンパイルが完了すると、hello.c と同じディレクトに hello
という実行ファイルが出来上がります。
-
この、hello ファイルをダブルクリックすると新しいターミナルのウィンドウが開き、
しばらくすると Hello アプリケーションが起動します。
-
ターミナルを開かずにダブルクリックで hello
アプリケーションを起動させる簡単な方法は、次のようにします。
- hello以外の適当な名前の新規フォルダを作ります。
- そのフォルダに hello 実行ファイルを入れます。
- 次に、そのフォルダの名前を Hello.app にしてください。
- macOS では、.app のついたフォルダは、.app という拡張子は非常時になり、
アプリケーションとなります。この仕組みのことを
アプリケーションバンドルと言います。
- この簡易方法では、フォルダの名前は実行ファイルと同じに死ねければなりません。
- 実行ファイルは hello ですが、フォルダの名前は Hello
と大文字で初めても大丈夫です。
- この Hello アプリケーションをダブルクリックすると、
ターミナルを開かずにアプリケーションが起動します。
- 以上は、簡易的なアプリケーションバンドルの作り方ですが、正式には次の
「アプリケーションバンドル」で説明します。
アプリケーションバンドル
macOS では、アプリケーションを、「アプリケーションバンドル」とよばれる特殊なフォルダで管理します。アプリケーションバンドルを使うとダブルクリックでターミナルを開かずにアプリケーションを起動できるようになります。
アプリケーションバンドルは次のようなディレクトリ構成になります。
Hello.app
+Contents
++Info.plist
++MacOS
+++hello
++Resources
+++Hello.icns
- Hello.app は、通常のフォルダの末尾に .app という拡張子をつけたものです。〜.app というフォルダは単一のアプリケーションのように表示されます
- アプリケーションバンドルを右クリックして「パッケージの内容を表示」を選ぶと、アプリケーションバンドルの中身にアクセスできます
- Hello.app の直下に Contents というフォルダを作ります
- Contens というフォルダの下に Info.plist というテキストファイルと、MacOS というフォルダと、Resources というフォルダを作ります
- MacOS の中に、先ほど作った hello 実行ファイルを入れます
- Resources の中に、.icns という拡張子のついたアイコンファイルを入れます
Info.plist
Info.plist は、xml 形式のテキストファイルです。このファイルにアプリケーションのいろいろな設定をしていきます。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "https://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>hello</string>
<key>CFBundleIconFile</key>
<string>Hello.icns</string>
<key>CFBundleName</key>
<string>Hello</string>
<key>NSPrincipalClass</keyv
<string>NSApplication</string>
</dict>
</plist>
- CFBundleDevelopmentRegion には、アプリケーションで使用する主要な言語を指定します
- CFBundleExecutable には、実行ファイルを指定します。
この方法で実行ファイルを指定する場合は、実行ファイル名とアプリケーション名を
同じにする必要はありません。
- CFBundleIconFile には、.icns 形式のアイコンファイルを指定します
- CFBundleName には、アプリケーションメニューに表示される名前を指定します。これを指定しないと実行ファイルの名前がアプリケーションメニューに表示されます
- NSPrincipalClass には、NSApplication を指定します
最小限、以上の5項目を設定すれば OK です
出来上がったアプリケーションバンドルをダブルクリックしても起動しない場合は、アプリケーションバンドルを他の場所(例えばデスクトップなど)に移動してダブルクリックしてみてください。一度起動できれば、そのあとは、どの場所に移動しても起動できます。
Linux
Fedora、CentOS、Ubuntu 16.04、Mint 18では、
コンパイルして出来上がった実行ファイルを、ダブルクリックで起動できます。
しかしアイコンはシステムのデフォルトアイコンになります。
Dbian、Ubuntu 18.04、Mint 19では、コンパイルして出来上がった実行ファイルを
ダブルクリックしても起動できません。アイコンもつきません。
しかしスタートメニューに登録することで
シングルクリックで起動できて任意のアイコンもつけることができます。
デスクトップエントリー
-
デスクトップエントリーというファイルを作り、そのファイルで実行ファイルやアイコン
などを指定することで、スタートメニューに登録されます。
-
実行ファイルは次のように名前を指定してコンパイルすると良いでしょう。
gcc hello.c `pkg-config --cflags --libs gtk+-3.0` -o hello
- 次にpng形式かsvg形式のアイコンを用意します。今回は下記の場所から適当なsvg
をコピーしてきました。あくまでもコピーして使ってください。
移動するとそのアイコンを必要とするアプリケーションから使えなくなります。
今回はLinux Mint 19.1 Mateからmate.svgというアイコンをコピーしました
/usr/share/icons/hicolor/scalable/apps
- 次に下記の場所にhello実行ファイルとアイコンファイルを移動します。
指定のディレクトリがないようでしたら作ってください。
/home/ユーザー名/.local/share/applications
-
そして、同じ場所に次の内容の hello.desktop というファイルを作ります。
hello.desktop
[Desktop Entry]
Type=Application
Version=1.0
Name=Hello
Exec=/home/ユーザー名/.local/share/applications/hello
Icon=/home/ユーザー名/.local/share/applications/mate.svg
Comment=My first application.
Categories=
- Versionはアプリケーションのバージョンではなく、
デスクトップエントリーの仕様バージョンです。記述しなくても問題ないみたいです。
- ExecとIconはフルパスで指定しなければいけません。
- Commentが有効になるのは私の環境ではLinux Mintだけでした。
- Categoriesは指定方法がわかりません。
逆に間違えて設定するとスタートメニューに登録されないことがありので
指定しないほうが良いかもしれません。指定しない場合は「その他」に分類されます。
- hello.desktopに間違いないかは次のコマンドで確認できます。
何も表示されなければエラーはありません。
desktop-file-validate hello.desktop
-
デスクトップエントリーの設定はすぐに有効になるOSもあれば
再ログイン後に有効になるOSもあるみたいです。
場所について
上記の方法はユーザー専用にアプリケーションを登録する方法でした。
システム全体(全ユーザー向け)に登録するには、
それぞれのファイルの場所を次のとおり変更します。
デスクトップエントリー
~/.local/share/applications // ユーザー専用
/usr/share/applications // システム全体
アプリケーション
~/.local/shara/applications // ユーザー専用
/usr/bin // システム全体
アイコン
~/.local/share/applications // ユーザー専用
もしくは
~/.local/share/icons/hicolor/scalable/apps // ユーザー専用
/usr/share/icons/hicolor/scalable/apps // システム全体
デスクトップエントリーの設定を反映させるために次のコマンドを使えるそうですが、
私の環境でエラーが出ます。再ログインのほうが良いように思います。
再ログインなしで設定が反映される場合もあります。
update-desktop-database
そしてデスクトップエントリーを次のように変更します。
hello.desktop
[Desktop Entry]
Type=Application
Version=1.0
Name=Hello
Exec=hello
Icon=mate.svg
Comment=My first application.
Categories=
/usr/binと/usr/share/icons/hicolor/scalable/appsには、
すでにパスが通っていますので、それぞれファイル名だけで大丈夫です。
ユーザー専用設定とシステム全体設定の両方が存在する場合は、
ユーザー専用設定が使われます。
Posted: Jan. 05, 2020
Update: Jan. 13, 2020