CodeGen_PECL で sary バインディング その2・解説編

引き続き、その1・紹介編に載せた spec ファイルのポイントを解説します。


まずは依存する libsary や glib のパスをどうするかという点ですが、幸いにして sary は pkg-config に対応しているので deps 要素の中に以下のような with 要素を書くだけで済みます。
(Windows ではまた勝手が違うと思うのですが、開発環境を用意していないのでわかりません)

<with name="sary" mode="pkg-config" testfile="include/sary.h">
	<header name="sary.h" />
	<header name="glib.h" />
</with>

mode="[]pkg-config[]" というのが肝で、これにより pkg-config がインストールされていれば、必要なヘッダさえ指定しておけば、ヘッダを読み込むディレクトリやリンクするライブラリは自動で設定してくれるようになります。
ちなみに mode 属性については CodeGen_PECL のサンプルにもドキュメントにも無く、CodeGen/PECL/Dependency/With.php にこっそり書かれているだけの状態です(たぶん)。発見したときはちょっと感動しました。


次に SarySearcher オブジェクトを格納するリソースですが、これは resources 要素の中に 以下のような resource 要素を書きます。

<resource name="sary_searcher" payload="SarySearcher" alloc="no">
	<destruct><![CDATA[
sary_searcher_destroy(resource);
	]]></destruct>
</resource>

SarySearcher オブジェクトは sary_seacher_new() で生成されるので alloc="no" とし、destruct 要素で sary_searcher_destroy() によって開放することを明示します。
CodeGen_PECL で自動生成されるリソースのデストラクタでは、リソースの実体の変数名は resource で固定のようです。


各関数の内容については端折りますが、リソースの扱いについて少し書いておきます。

  • 関数のプロトタイプで resource res_type var_name としたリソースは C では 2種類の変数が定義される。
    • zval * var_name
    • (res_type に対応する型) res_var_name
  • リソースを返す関数では変数 return_res が定義され、これにリソースの実体を代入すれば後はよきに計らってくれる。
  • リソースを開放する関数では FREE_RESOURCE マクロを使うべし。
    • 下手に自前で開放しようとすると SEGV/bus error の元となる。


あと CodeGen_PECL 固有の話ではありませんが、 気になったことを一つ。
libsary のリファレンスマニュアルでは sary_searcher_get_next_line() の返り値は後から g_free() する必要があると書かれているのですが、今回作成したバインディングでそのようにすると二重開放になってしまいました。
return_value に設定した文字列は zval のデストラクタにおいて efree() されるので開放不要と理解しましたが、何となく気持ち悪いです。
(しかもこの場合は代入じゃなくてコピーしてるんだけど...自分の理解がおかしいのかな...?)


その1で紹介した spec ファイルを見る限りではすごく簡単に見えますが(実際かなり楽なのですが)、pecl-gen 一発でいけるようなのを書くのにはそれなりの学習コストがかかりましたよというお話。