Visual Studio 2017 Professional、もしくはVisual Studio 2017 Express for Desktopで実行する。(どちらでも動作した。)
GtkSharpが実行するフレームワークは、Windows環境下であればDotNetFramework4.7以降を使用する。
まずは通常のWindowsアプリとしてプロジェクトを作成する。(Consoleで作成してからWindowにしてもよいし、WindowsFormで作成してFormを全部消してもよい)
次に、NuGetを使って、Mike KestnerさんのGtkSharp.Win32を導入する。
これは、公式のGtkSharpのアセンブリに加えて、それが必要とするネイティブライブラリを導入する。
基本、これだけでGtkSharpによるGTKウィンドウアプリは作成・実行可能になる。
※ 公式のGtkSharpのアセンブリだけだと、ビルドはできるが実行時にネイティブライブラリが見つからず起動できない。(MSys2のGtkのネイティブライブラリにパスを通してあれば動作する)
なお、GtkSharp.Win32がコピーするGtkのネイティブライブラリは32ビット版だけのため、プロジェクトは32ビットでビルドする必要がある。
すでに packages.config
に依存関係として登録してあるので、これを復元するには、
パッケージクネージャコンソールを開き、
Update-Package -reinstall
でパッケージを復元することができる。
もしくはNuGet CLIを導入していれば、コマンドラインから
nuget restore
でパッケージを復元することができる。
いくつかの環境で試したところ、
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="AtkSharp" version="3.22.24.10" targetFramework="net47" />
<package id="CairoSharp" version="3.22.24.10" targetFramework="net47" />
<package id="GdkSharp" version="3.22.24.10" targetFramework="net47" />
<package id="GioSharp" version="3.22.24.10" targetFramework="net47" />
<package id="GLibSharp" version="3.22.24.10" targetFramework="net47" />
<package id="GtkSharp" version="3.22.24.10" targetFramework="net47" />
<package id="GtkSharp.Win32" version="3.1.2" targetFramework="net47" />
<package id="PangoSharp" version="3.22.24.10" targetFramework="net47" />
</packages>
GtkSharpの3.22.24.??
の末尾の数字が37だと、実行時にネイティブライブラリとのミスマッチが発生して実行できない事象があった。
GtkSharpと、GtkSharp.Win32との間でバージョン連携が取れていないのではないかと思われる。
とりあえず、古いバージョンを指定しておけばOKか? (NuGetで普通にいれると最新が入るので注意)
また、フレームワークのバージョンを 4.7 から 4.7.1 に変えると、上記バージョンが指定できる範囲も変わってくるので、結構センシティブな感じである。
GtkSharpをNuGetで導入すると「アセンブリ 'netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' に参照を追加する必要があります。」というエラーが出てコンパイルできなくなっている場合がある。
GtkSharpはNetStandard 2.0互換で作成されているライブラリで、DotNet Framework 4.7 であればDotNet Standard 2.0互換のはず。よって明示的にNuGetから入れるようなものではない(というか探しても出てこない)はずだが、このマッピングがうまくいっていないらしい?
VS2017のソースコード編集画面で赤波線が引かれているところで「ALT+ENTER」を押して「考えられる修正を表示」サジェストを表示して、「参照を'netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'に追加」みたいな表示があれば、ここで「ENTER」キーを押せば、これらの設定がされてエラーは消える。
何らソース等いじる必要はない。
(package.configには変化はないが、プロジェクトの参照ツリーの下でnetstandardの参照が追加されている。プロジェクトファイルの何かが変わっているのだろうが、ソース管理しているファイル上には変化がないのでdiffとっても違いが分からず厄介である。)
GtkSharpを使うにあたり、MSys2のGtkは事前にインストールしておく必要がある。
pacman -S mingw-w64-x86_64-gtk3
pacman -S mingw-w64-i686-gtk3
64bit, 32bitの両方のgtkを導入しておくことで、プロジェクトは、それぞれx64, x86のいずれでもビルドできるようになる。
※ Visual Studioからデバックする場合は64ビット版を使う。
GUIのレイアウトにはGladeによるXML形式のレイアウト定義ファイルを使っている。
Windowsの場合は、MSys2 からGTK3, Glade関連を導入することができる。
pacman -S mingw-w64-x86_64-gtk3 mingw-w64-x86_64-glade
これでgladeが得られたら、
msys2 MinG64
環境下のbashを開いて
glade Form1.glade
のようなコマンドで編集することができる。
パッケージの復元ができていれば、あとはプロジェクトをVisual Studioで開くか、msbuild
から直接ビルドできる。
ビルドすると、bin出力フォルダ下にネイティブライブラリのコピーされ、実行可能なexeが作成される。
bin\debug下には以下のようなMSys2のGtk3ネイティブライブラリを含むdllもコピーされているようである。
AtkSharp.dll
CairoSharp.dll
GdkSharp.dll
GioSharp.dll
GLibSharp.dll
GtkSharp.dll
PangoSharp.dll
iconv.dll
libatk-1.0-0.dll
libcairo-2.dll
libcairo-gobject-2.dll
libffi-6.dll
libgcc_s_sjlj-1.dll
libgdk-3-0.dll
libgdk_pixbuf-2.0-0.dll
libgio-2.0-0.dll
libglib-2.0-0.dll
libgmodule-2.0-0.dll
libgobject-2.0-0.dll
libgtk-3-0.dll
libintl-8.dll
libpango-1.0-0.dll
libpangocairo-1.0-0.dll
libpangowin32-1.0-0.dll
libpixman-1-0.dll
libpng16-16.dll
libwinpthread-1.dll
zlib1.dll
SimpleGtkSharpAndGladeExample.exe
SimpleGtkSharpAndGladeExample.exe.config
SimpleGtkSharpAndGladeExample.pdb
MSys2のGtkまわりに環境変数PATHを通してなくても、このexeを実行すればGtk3の画面が開く。
GtkSharp.Win32は、GtkSharpを依存関係として公式のGtkSharpのアセンブリをロードさせ、且つ、 ビルド時に自分が抱えているGtkまわりのdllをexeと同じ出力ディレクトリにコピーしているだけのようである。
1> "C:\Users\seraphy\git\GtkSharpExample\packages\GtkSharp.Win32.3.1.2\build\net45\libcairo-gobject-2.dl_" から "bin\Debug\\libcairo-gobject-2.dll" へファイルをコピーしています。
1> "C:\Users\seraphy\git\GtkSharpExample\packages\GtkSharp.Win32.3.1.2\build\net45\libffi-6.dl_" から "bin\Debug\\libffi-6.dll" へファイルをコピーしています。
1> "C:\Users\seraphy\git\GtkSharpExample\packages\GtkSharp.Win32.3.1.2\build\net45\iconv.dl_" から "bin\Debug\\iconv.dll" へファイルをコピーしています。
1> "C:\Users\seraphy\git\GtkSharpExample\packages\GtkSharp.Win32.3.1.2\build\net45\libgcc_s_sjlj-1.dl_" から "bin\Debug\\libgcc_s_sjlj-1.dll" へファイルをコピーしています。
1> "C:\Users\seraphy\git\GtkSharpExample\packages\GtkSharp.Win32.3.1.2\build\net45\libcairo-2.dl_" から "bin\Debug\\libcairo-2.dll" へファイルをコピーしています。
1> "C:\Users\seraphy\git\GtkSharpExample\packages\GtkSharp.Win32.3.1.2\build\net45\libatk-1.0-0.dl_" から "bin\Debug\\libatk-1.0-0.dll" へファイルをコピーしています。
1> "C:\Users\seraphy\git\GtkSharpExample\packages\GtkSharp.Win32.3.1.2\build\net45\libgdk-3-0.dl_" から "bin\Debug\\libgdk-3-0.dll" へファイルをコピーしています。
1> "C:\Users\seraphy\git\GtkSharpExample\packages\GtkSharp.Win32.3.1.2\build\net45\libgio-2.0-0.dl_" から "bin\Debug\\libgio-2.0-0.dll" へファイルをコピーしています。
1> "C:\Users\seraphy\git\GtkSharpExample\packages\GtkSharp.Win32.3.1.2\build\net45\libgdk_pixbuf-2.0-0.dl_" から "bin\Debug\\libgdk_pixbuf-2.0-0.dll" へファイルをコピーしています。
1> "C:\Users\seraphy\git\GtkSharpExample\packages\GtkSharp.Win32.3.1.2\build\net45\libglib-2.0-0.dl_" から "bin\Debug\\libglib-2.0-0.dll" へファイルをコピーしています。
1> "C:\Users\seraphy\git\GtkSharpExample\packages\GtkSharp.Win32.3.1.2\build\net45\libgmodule-2.0-0.dl_" から "bin\Debug\\libgmodule-2.0-0.dll" へファイルをコピーしています。
1> "C:\Users\seraphy\git\GtkSharpExample\packages\GtkSharp.Win32.3.1.2\build\net45\libgobject-2.0-0.dl_" から "bin\Debug\\libgobject-2.0-0.dll" へファイルをコピーしています。
1> "C:\Users\seraphy\git\GtkSharpExample\packages\GtkSharp.Win32.3.1.2\build\net45\libgtk-3-0.dl_" から "bin\Debug\\libgtk-3-0.dll" へファイルをコピーしています。
1> "C:\Users\seraphy\git\GtkSharpExample\packages\GtkSharp.Win32.3.1.2\build\net45\libintl-8.dl_" から "bin\Debug\\libintl-8.dll" へファイルをコピーしています。
1> "C:\Users\seraphy\git\GtkSharpExample\packages\GtkSharp.Win32.3.1.2\build\net45\libpango-1.0-0.dl_" から "bin\Debug\\libpango-1.0-0.dll" へファイルをコピーしています。
1> "C:\Users\seraphy\git\GtkSharpExample\packages\GtkSharp.Win32.3.1.2\build\net45\libpangocairo-1.0-0.dl_" から "bin\Debug\\libpangocairo-1.0-0.dll" へファイルをコピーしています。
1> "C:\Users\seraphy\git\GtkSharpExample\packages\GtkSharp.Win32.3.1.2\build\net45\libpangowin32-1.0-0.dl_" から "bin\Debug\\libpangowin32-1.0-0.dll" へファイルをコピーしています。
1> "C:\Users\seraphy\git\GtkSharpExample\packages\GtkSharp.Win32.3.1.2\build\net45\libpixman-1-0.dl_" から "bin\Debug\\libpixman-1-0.dll" へファイルをコピーしています。
1> "C:\Users\seraphy\git\GtkSharpExample\packages\GtkSharp.Win32.3.1.2\build\net45\libpng16-16.dl_" から "bin\Debug\\libpng16-16.dll" へファイルをコピーしています。
1> "C:\Users\seraphy\git\GtkSharpExample\packages\GtkSharp.Win32.3.1.2\build\net45\libwinpthread-1.dl_" から "bin\Debug\\libwinpthread-1.dll" へファイルをコピーしています。
1> "C:\Users\seraphy\git\GtkSharpExample\packages\GtkSharp.Win32.3.1.2\build\net45\zlib1.dl_" から "bin\Debug\\zlib1.dll" へファイルをコピーしています。
GtkSharp.Win32
は、2015年のFramework4.5時代からメンテされていないので、早晩、使えなくなることが予想される。
しかし、GtkSharp.Win32
がやっていることはネイティブライブラリのコピーだけのようだと分かったので、自分で試してみる。
GtkSharpの公式ページのインストール手順にあるとおり、まずはMSys2のdllを参照できれば、普通に機能するはずではないか、と思い試してみた。
この環境ではMsys2のGtk3は64ビット版しか入れていないので、まず、本アプリを64ビットとしてビルドし直す。
つぎに、生成された上記lib????.dllを削除して明示的にパスを通して実行してみる。
SET PATH=C:\msys64\mingw64\bin
bin\Debug\SimpleGtkSharpAndGladeExample.exe
で、問題なく表示できた。
(C#側をx86でビルドしていたことを失念していてエラーになったりしたのだが、x64ビルドしたら、あっさり通った。)
この環境のMSys2には64ビット版のGtk3しか入れていないので、プロジェクトを64ビットビルドに変更して、
依存関係からGtkSharp.Win32
を切って、GtkSharp
だけにし、
Update-Package -reinstall
によって、パッケージを入れなおす。(バージョンは最新のGtkSharpで問題ない。)
この状態でビルドしなおす。
当然、ネイティブライブラリはコピーされていないが、まずは、前述のとおり、明示的にパスを通せば動くことを確認する。
つぎにMSys2
からGtk3まわりのdllを直接コピーしてみる。(copy_libs.bat参照)
GtkSharp.Win32
がコピーしていたファイルをもとに、1つづつ試した結果、以下のものをコピーしたら、とりあえず動くようになった。
(ウェジットによっては更に必要なものもあるのかもしれないが)
libatk-1.0-0.dll
libbz2-1.dll
libcairo-2.dll
libcairo-gobject-2.dll
libdatrie-1.dll
libepoxy-0.dll
libexpat-1.dll
libffi-6.dll
libfontconfig-1.dll
libfreetype-6.dll
libfribidi-0.dll
libgcc_s_seh-1.dll
libgdk-3-0.dll
libgdk_pixbuf-2.0-0.dll
libgio-2.0-0.dll
libglib-2.0-0.dll
libgmodule-2.0-0.dll
libgobject-2.0-0.dll
libgraphene-1.0-0.dll
libgraphite2.dll
libgtk-3-0.dll
libharfbuzz-0.dll
libiconv-2.dll
libintl-8.dll
libpango-1.0-0.dll
libpangocairo-1.0-0.dll
libpangoft2-1.0-0.dll
libpangowin32-1.0-0.dll
libpcre-1.dll
libpixman-1-0.dll
libpng16-16.dll
libstdc++-6.dll
libthai-0.dll
libwinpthread-1.dll
zlib1.dll
これでパスを通してなくても、エクスプローラからexeを直接起動できるようになった。
http://grbd.github.io/posts/2016/06/25/gtksharp-part-3-basic-example-with-vs-and-glade/