Poppler 0.22.5の.NETバインディングを作成する

MinGWでビルドしたPoppler 0.22.5の.NETバインディングを作成する。Windows単体ではすんなり作成できそうにないので、LinuxXubuntu)で作業した。

必要な環境

monoの開発環境。

XubuntoでMonoDevelop 4が動かしたくて色々入れた後なので、どのパッケージが必要かどうかとか確認してない。ちなみにMonoDevelop 4をコンパイルはInstall MonoDevelop 4 under Ubuntu 12.04 LTS from sourcesの手順でやっている。

手順

GAPI - Monoという、GLib依存APIバインディングコードを自動生成するやつを使う。当然、Popplerは--enable-glibを指定してコンパイルしている前提。

  1. Popplerのソースをダウンロードしてきて展開
  2. generaterの設定ファイルを作成
    • .sourcesは後述
  3. gapi2-parserに.sourcesを食わせてAPIファイル(.raw)を生成
    • gapi2-parser poppler-api.sources
  4. gapi2-fixupでAPIファイルにパッチをあてる
    • cp poppler-api.raw poppler-api.xml
    • gapi2-fixup --api=poppler-api.xml --metadata=poppler-api.metadata
    • .metadataは後述
  5. gapi2-codegenにパッチ適用済みのAPIファイルを食わせるコードを生成
  6. コンパイル
    • 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#をインストールすれば同梱されているので、これを流用する。

補足

Popplerの.NETバインディング自体はPdfModがおそらく同じ方法で作成しているようだ。GPLであることを気にしなければ、これを流用してしまうのもありかもしれない。あと、debian系のディストリビューションではpoppler-sharpという名前でパッケージが配布されている。

自分の場合はMinGWでビルドしたものを使いたい(DllImportのパスをMinGWに合わせなくてはいけない)のと、GPLにはしたくないなぁというのがあったので、自前でコードを生成した。(ちなみにGTK#, glib-sharp, Mono.CairoはLGPL