PHP7 で yrmcds クライアントの拡張を動くようにした

先日 PHP のメジャーバージョンである PHP7 がリリースされました。 性能向上のために内部構造が大きく変更されているため、PHP5 向けの拡張モジュールは大幅に書き直しが必要です。

拡張モジュールを開発したことがある人はご存知の通り、PHP の内部 API は公式の解説がほとんどありません。 必然、先人の資料や本体のコードを読み漁ってなんとかするわけで、以下の資料を大いに参考にいたしました。

実際の対応については、以下のようにしました。

  1. PHP5 と PHP7 でソースコードを分ける
    Divide source code for PHP5 and 7. · cybozu/php-yrmcds@353f917 · GitHub
    config.m4PHP のバージョンを検出して、PHP5 と PHP7 で別のソースコードコンパイルするように。
  2. 変更されたと明記されている API をちまちま直す
    TSRMLS_* マクロの削除文字列長の型を int から size_t に修正するなど。
  3. クラスとリソースの実装を大幅に変更する
    リソースをやめてオブジェクト内部にソケットを保持するように変更するなど。
  4. ZEND_TSRMLS_CACHE_* マクロを追加
    ext_skel の生成するスケルトンコードに追加されていたので、PHP7 のソースコードに追加
  5. コンパイルして、ほかに必要な API 変更がないか見てみる
    ここまでの修正が済んでいれば、あと必要な変更はほんの少しだけではないかと思います。
    私の場合、zend_register_internal_class_ex の第三引数が PHP7 では不要になっていた、くらいでした。
  6. make test でテストを通す
    もちろん PHP5 と PHP7 の両方で試します。
    実はこれまで *.phpt の形式にしていなかったのですが、いい機会なので大幅にテストを足しました

PHP5 と PHP7 でソースコードを分けるか否か迷うかもしれませんが、もし拡張が内部クラスやリソース、あるいはハッシュテーブルの API を利用している場合、変更が大きすぎるので分けたほうが良いと思います。

最後に感想ですが、PHP7 の内部 API はすごく洗練されたのが作業を通じて理解できました。 PHP5 からのポーティングは大変面倒ですが、PHP7 向けに拡張を書くのはこれまでよりずっと合理的で理解しやすくなっていると思います。

雑なメモですが、どなたかのお役に立てば。