自分でビルドしたPoppler 0.22.5 + .NETバインディングがうまく動かなかった
ここ数日、Popplerを自分でビルドしたりして.NETから叩いてみてたんだけど、どうも動作が不安定。
こんな感じのコードが動いたり、AccessViolationException(メモリ破壊)が起こったり、動作が安定しない。
var document = Poppler.Document.NewFromFile("file:///path/to/src.pdf", String.Empty); var page = document.GetPage(0); var surface = new Cairo.ImageSurface(Cairo.Format.Argb32, 300, 300); var cairo = new Cairo.Context(surface); page.Render(cairo); surface.WriteToPng("out.png"); // ここで死ぬ surface.Dispose(); page.Dispose(); document.Dispose();
原因がはっきりしないのだけど、どうもCairoがうまく動いてないみたい。調査をするのも大変だし、ビルドしなおすのも大変(依存ライブラリが多すぎる)ので、とりあえずPopplerを見切って他の物を調べることにした。
Poppler 0.22.5の.NETバインディングを作成する
MinGWでビルドしたPoppler 0.22.5の.NETバインディングを作成する。Windows単体ではすんなり作成できそうにないので、Linux(Xubuntu)で作業した。
必要な環境
monoの開発環境。
XubuntoでMonoDevelop 4が動かしたくて色々入れた後なので、どのパッケージが必要かどうかとか確認してない。ちなみにMonoDevelop 4をコンパイルはInstall MonoDevelop 4 under Ubuntu 12.04 LTS from sourcesの手順でやっている。
手順
GAPI - Monoという、GLib依存APIのバインディングコードを自動生成するやつを使う。当然、Popplerは--enable-glibを指定してコンパイルしている前提。
- Popplerのソースをダウンロードしてきて展開
- generaterの設定ファイルを作成
- .sourcesは後述
- gapi2-parserに.sourcesを食わせてAPIファイル(.raw)を生成
- gapi2-parser poppler-api.sources
- gapi2-fixupでAPIファイルにパッチをあてる
- gapi2-codegenにパッチ適用済みのAPIファイルを食わせるコードを生成
- コンパイル
- mcs -pkg:gtk-sharp-2.0 -pkg:mono-cairo -target:library -unsafe -o poppler-sharp.dll generate/*.cs
poppler-api.sources
<gapi-parser-input> <api filename="poppler-api.raw"> <library name="libpoppler-glib-8.dll"> <namespace name="Poppler"> <dir>/home/terurou/poppler-0.22.5/glib</dir> </namespace> </library> </api> </gapi-parser-input>
poppler-api.metadata
<?xml version="1.0" encoding="UTF-8"?> <metadata> <add-node path="/api"> <symbol type="manual" cname="cairo_t" name="Cairo.Context" /> </add-node> <add-node path="/api"> <symbol type="manual" cname="GdkPixbuf" name="Gdk.Pixbuf" /> </add-node> <attr path="/api/namespace/enum[@name='Permissions']" name="hidden">1</attr> <attr path="/api/namespace/object[@name='Action']" name="parent">GObject</attr> <attr path="/api/namespace/object[@name='Annot']" name="parent">GObject</attr> <attr path="/api/namespace/struct[@name='AnnotCalloutLine']" name="opaque">false</attr> <attr path="/api/namespace/object[@name='AnnotFreeText']" name="parent">GObject</attr> <attr path="/api/namespace/struct[@name='AnnotMapping']" name="opaque">false</attr> <attr path="/api/namespace/object[@name='AnnotMovie']" name="parent">GObject</attr> <attr path="/api/namespace/object[@name='AnnotScreen']" name="parent">GObject</attr> <attr path="/api/namespace/object[@name='AnnotText']" name="parent">GObject</attr> <attr path="/api/namespace/struct[@name='Color']" name="opaque">false</attr> <attr path="/api/namespace/struct[@name='Dest']" name="opaque">false</attr> <attr path="/api/namespace/struct[@name='FormFieldMapping']" name="opaque">false</attr> <attr path="/api/namespace/struct[@name='ImageMapping']" name="opaque">false</attr> <attr path="/api/namespace/struct[@name='LinkMapping']" name="opaque">false</attr> <attr path="/api/namespace/object[@name='Media']" name="parent">GObject</attr> <attr path="/api/namespace/object[@name='Movie']" name="parent">GObject</attr> <attr path="/api/namespace/struct[@name='PageTransition']" name="opaque">false</attr> <attr path="/api/namespace/struct[@name='Rectangle']" name="opaque">false</attr> <attr path="/api/namespace/struct[@name='TextAttributes']" name="opaque">false</attr> </metadata>
使用する際の注意
glib-sharpとMono.Cairoに依存したコードが生成されるので、実行する場合はこれ必要になる。Windowsの場合はGTK#をインストールすれば同梱されているので、これを流用する。
MinGWでPoppler 0.22.5をビルド
依存ライブラリが多くて疲れた…。ビルドした後から手順を書いてるので間違ってるかも。
インストール手順メモ
- MinGW
- GLib, gettext, pkg-configのバイナリを/MinGWにぶち込む
- Python 2.7.5
- パスを通しておく。Chocolateyとかで入れると楽。
- zlib 1.2.8
- libpng 1.6.2
- ./configure --prefix=/mingw
- make
- make install
- libjpeg v9
- libjpeg-turboだとPopplerのconfigureを通せなかった
- ./configure --prefix=/mingw
- make
- make install
- XZ Utils 5.0.5
- ./configure --prefix=/mingw
- make
- make install
- LibTIFF 4.0.3
- ./configure --prefix=/mingw
- make
- make install
- Little CMS 2.5
- ./configure --prefix=/mingw
- make
- make install
- OpenJPEG 1.5.1
- ./configure --prefix=/mingw
- make
- make install
- freetype 2.5.0
- ./configure --prefix=/mingw
- make
- make install
- nkf 2.1.2(fontconfigの確認ためだけなので要らないと思う)
- make
- make install --prefix=/mingw
- libxml2 2.9.1(git snapshot)
- ./configure --prefix=/mingw
- make
- make install
- fontconfig 2.10.93
- ./configure --prefix=/mingw --enable-libxml2
- make
- make install
- confの設定(詳細は http://oku.edu.mie-u.ac.jp/~okumura/texwiki/?poppler)
- pixman 0.30.0
- Cairo 1.12.14
- ./configure --prefix=/mingw
- echo "#define _SSIZE_T_DEFINED 1" >> config.h
- make
- make install
- libffi 3.0.13
- ./configure --prefix=/mingw
- make
- make install
- GLib 2.37.3
- CFLAGS="-Wall -Ofast -march=native" ./configure --prefix=/mingw
- make
- make install
- OpenSSL 1.0.1e(Popplerで--enable-libcurlを指定しない場合は不要)
- tarで展開しないとmakeが失敗する(undefined reference to `_WinMain@16' with cygwin and mingw in openssl - Stack Overflow
- ./config --prefix=/mingw shared
- make
- make install
- curl 7.31.0(Popplerで--enable-libcurlを指定しない場合は不要)
- ./configure --prefix=/mingw
- make
- make install
- poppler 0.22.5
- ./configure --prefix=/mingw --with-font-configuration=fontconfig --enable-xpdf-headers --enable-zlib --enable-libcurl --enable-poppler-glib --disable-poppler-qt4 --disable-poppler-cpp --disable-gtk-test
- make
- make install