【PHPext】PHP拡張モジュールの作成

2010-07-29 (木) 21:55:42 (37d)

構築環境:Fedora Core 3, Kernel 2.6.10-1.770, autoconf 2.59, automake 1.9.2, gcc 3.4.2,PHP 4.3.x-dev

PHP拡張モジュール

長所

  • 既存のCのライブラリを使える
  • 高速(これはApacheモジュールにしたほうが有利かも)

短所

  • プログラミングに時間がかかる
  • モジュールの内容を変更するには再コンパイルが必要

普通のPHPerな人間はあんまり使わない。

準備/必要なもの

  1. C言語を操れる脳みそ
  2. autoconf/automake/libtool/gcc
  3. awk*1
  4. PHPのsnapshotのコード*2

手順

PHP拡張モジュールを作成する手順は以下のようになります。

プロトタイプファイルとは モジュールに含まれる関数名を羅列したテキストファイルです。
プロトタイプファイルをext_skelスクリプトで処理すると、コードの基本的な部分が自動生成されます。

  1. プロトタイプファイルの作成
  2. ext_skelによる、コードの生成
  3. config.m4の編集
  4. configureスクリプトの生成
  5. コーディング
  6. コンパイル

サンプル モジュールの作成

下記のような関数を含むモジュ-ルを作成してみる。モジュール名は「sample_funcs」とする。

void omikuji()
「daikichi(^-^)」「cyu-kichi(-_-)」「kyo(T_T)」のそれぞれを3分の1の確立で表示する。
string orz([bool isCapital])
isCapitalがTRUEなら「Orz」、FALSEなら「orz」と返す。isCapitalは省略可能で、デフォルトは小文字。

プロトタイプの記述(関数の定義ファイル)

[型] 関数名(引数) [コメント]

型とコメントはオプションです。コードのコメントとして記載されるだけです。

  • filesample_funcs.proto
    void omikuji() Return Fortune Telling result.
    string orz([bool isCapital]) Return orz.

ext_skelによるコードの生成

ext_skelスクリプトを動かします。sample_funcsフォルダとコードが自動生成されます。

# cd ext/
# ./ext_skel --extname=sample_funcs --proto=sample_funcs.proto

config.m4の編集

config.m4の16、18行目のコメントアウトをはずします(dnlを消す)。
これによりconfigureスクリプトで--enable-sample_funcsと指定することが出来るようになります。

  • fileconfig.m4
    16: PHP_ARG_ENABLE(sample_funcs, whether to enable sample_funcs support,
    17: dnl Make sure that the comment is aligned:
    18: [  --enable-sample_funcs           Enable sample_funcs support])

configureスクリプトの生成

buidconfスクリプトを動かすとconfig.m4をもとに、自動的にconfigureスクリプトが生成または更新されます。

# cd ../
# ./buildconf

autoheaderがWARNING吐きだすけど、自分のせいじゃないのでとりあえず無視する(笑)*3

using default Zend directory
rebuilding configure
rebuilding main/php_config.h.in
autoheader: WARNING: Using auxiliary files such as `acconfig.h', `config.h.bot'
autoheader: WARNING: and `config.h.top', to define templates for `config.h.in'
autoheader: WARNING: is deprecated and discouraged.
autoheader: 
autoheader: WARNING: Using the third argument of `AC_DEFINE' and
autoheader: WARNING: `AC_DEFINE_UNQUOTED' allows to define a template without
autoheader: WARNING: `acconfig.h':
autoheader: 
autoheader: WARNING:   AC_DEFINE([NEED_FUNC_MAIN], 1,
autoheader:             [Define if a function `main' is needed.])
autoheader: 
autoheader: WARNING: More sophisticated templates can also be produced, see the
autoheader: WARNING: documentation.

コーディング

sample_funcs.cを編集し、実際に関数の中身をコーディングする。

#cd ext/sample_funcs.c
#vi sample_funcs.c

rand()、srand()用にstdlib.h, time.hをincludeする。

#include <stdlib.h>
#include <time.h>

/* {{{ proto void omikuji()
   Return Fortune Telling result. */
PHP_FUNCTION(omikuji)
{
    if (ZEND_NUM_ARGS() != 0) { 
        WRONG_PARAM_COUNT;
    }

    srand((unsigned int)time(NULL));
    switch (rand() % 3) {
        case 0: 
            php_printf("%s", "daikichi(^-^)");
            break;
        case 1:
            php_printf("%s", "cyu-kichi(-_-)");
            break;
        default:
            php_printf("%s", "kyo(T_T)");
            break;
    }

    /* php_error(E_WARNING, "omikuji: not yet implemented"); */
}
/* }}} */ 

/* {{{ proto string orz([bool isCapital])
   Return orz. */
PHP_FUNCTION(orz)
{
    int argc = ZEND_NUM_ARGS();
    zend_bool isCapital;

    if (zend_parse_parameters(argc TSRMLS_CC, "|b", &isCapital) == FAILURE)
        return;

    if (isCapital) {
        RETVAL_STRING("Orz", 1);
    } else {    
        RETVAL_STRING("orz", 1);
    }
    /* php_error(E_WARNING, "orz: not yet implemented"); */
}
/* }}} */

各関数の説明はこちら

コンパイル

configureに--enable-sample_funcsを付けて実行する。

#cd ../../
#./configure --enable-sample_funcs
#make

開発中は、make installをしないで、既存のPHP環境は残しておいたほうが無難

動かしてみる

まずは、phpinfo()にsample_funcsの項目が追加されているか確認する。

#echo '<?php phpinfo() ?>' | ./sapi/cli/php | grep sample_funcs
Configure Command =>  './configure' '--enable-sample_funcs'
sample_funcs
sample_funcs support => enabled

となっていればOK。なっていなければ、config.m4が間違っているか、configureスクリプト が更新されていないので、チェックしよう。

あとは同様の方法で動作をチェックする。

#echo '<?php omikuji(); ?>' | ./sapi/cli/php
#echo '<?php echo orz(); ?> | ./sapi/cli/php
#echo '<?php echo orz(TRUE); ?> | ./sapi/cli/php
#echo '<?php echo orz(FALSE); ?> | ./sapi/cli/php

参考資料

&amazon(1411601882, image);


*1 ext_skelスクリプトを動かすのに必要
*2 正式リリースのコードを変更しようとするとWARNINGが出る
*3 何も手を加えてないコードでbuildconfしてもWARNINGは出た

添付ファイル: filesample_funcs.proto 797件 [詳細] filesample_funcs.c 614件 [詳細] fileconfig.m4 652件 [詳細]