魔法少女好きだったらわかるphp拡張の作り方。

ひぎぃっ

動作するサンプルのダウンロード

プログラム
http://rtilabs.net/files/2011_02_13/mytest1.tar.gz

1.事前準備

必要なソフトウェアを適当に入れる。
何も考えずに実行。考えるな感じるんだ!

yum -y install m4 autoconf automake libtool gcc php-devel

2.phpのソースをもってくる

php のソースを適当にダウンロードして展開する.
http://php.net/downloads.php

wget http://www.php.net/get/php-5.3.5.tar.bz2/from/jp.php.net/mirror
tar Ixvf php-5.3.5.tar.bz2

3.extディレクトリに移動

extディレクトリに移動する。
男の子は、だまって移動するものだ。

cd php-5.3.5/ext

4.拡張の名前を適当に考える。

考えたけど、適当な名前が思いつかなかったので、とりあえず mytest。
mytest 雛形を作ってもらう。

./ext_skel --extname=mytest --proto=mytest.proto

すると、 php-5.3.5/ext/mytest ディレクトリが作成されて、
中身にスケルトンが作成される。やったー☆


注意

今回は mytest って名前の拡張なので mytest です。
あなたの拡張が hoehoe だったら、 mytest を hoehoe と読み替えてください。
あなたの拡張が hachimitu_boy だったら、 mytest は hachimitu_boy です。
これは、アジシオ太郎でも同じです。

5.出来たディレクトリに移動

作ってもらったディレクトphp-5.3.5/ext/mytest に移動する
だまって移動する

cd mytest

はい。ちゃんと php-5.3.5/ext/mytest まで移動できましたかー?移動出来ていない人は手を上げてください。

6.config.m4 の dnl を削る

--enable-mytest ってオプションを有効にするべく、 config.m4 の dnl を削る。
うちの環境だと16行目あたり

vi config.m4
----------------------------------------------------------
dnl PHP_ARG_ENABLE(mytest, whether to enable mytest support,
dnl Make sure that the comment is aligned:
dnl [  --enable-mytest           Enable mytest support])

↓↓↓↓↓↓↓↓↓変更↓↓↓↓↓↓↓↓↓↓↓↓

PHP_ARG_ENABLE(mytest, whether to enable mytest support,
Make sure that the comment is aligned:
[  --enable-mytest           Enable mytest support])
----------------------------------------------------------

7.とりあえずビルドしてみる。

ビルドが通るはず。

phpize
./configure
make

ビルドの成果物は php-5.3.5/ext/mytest/modules/mytest.so になる。

8.テスト用スクリプトを準備

ディフォルトで confirm_mytest_compiled というテスト用の関数が定義されているのでそれを呼び出してみる。
(こーゆー初心者にも親切丁寧というのが phpのいいところだな。見習いたい。)
呼び出し用の test.php をつくって、、、

vi test.php
--------------------------------------------------------
<?php

        echo confirm_mytest_compiled("abc");
--------------------------------------------------------

9.呼び出す!

ごーごー

php -d extension=modules/mytest.so  test.php

-----------------結果-----------------------------------
Congratulations! You have successfully modified ext/mytest/config.m4. Module abc is now compiled into PHP.
-------------------------------------------------------


動いた。abcのパラメータも渡った!!
やったね☆。
#完成したら、 make install するよろし。 /usr/lib/php/modules/ の中に入るよ。
#test.php を作らないで↓のようにやるワンライナーもいけるらしいよ
#php -d extension=modules/mytest.so -r 'echo confirm_mytest_compiled("abc");'

10.ソースを見て楽しむ

ソースを眺めよう。
ディフォルトで動作する confirm_mytest_compiled 関数があるわけだから、これで検索してみよう。

vi mytest.c
-----------------------------------------------------

//ここが関数エントリーに追加ね。
/* {{{ mytest_functions[]
 *
 * Every user visible function must have an entry in mytest_functions[].
 */
const zend_function_entry mytest_functions[] = {
        PHP_FE(confirm_mytest_compiled, NULL)           /* For testing, remove later. */
        {NULL, NULL, NULL}      /* Must be the last line in mytest_functions[] */
};
/* }}} */



//で、ここが実態なわけだ
/* Every user-visible function in PHP should document itself in the source */
/* {{{ proto string confirm_mytest_compiled(string arg)
   Return a string to confirm that the module is compiled in */
PHP_FUNCTION(confirm_mytest_compiled)
{
        char *arg = NULL;
        int arg_len, len;
        char *strg;

        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) == FAILURE) {
                return;
        }

        len = spprintf(&strg, 0, "Congratulations! You have successfully modified ext/%.78s/config.m4. Module %.78s is now compiled into PHP.", "mytest", arg);
        RETURN_STRINGL(strg, len, 0);
}
-----------------------------------------------------

ここではまだ触れないけど、 php_mytest.h に宣言があるよ。

vi php_mytest.h
-----------------------------------------------------
PHP_FUNCTION(confirm_mytest_compiled);  /* For testing, remove later. */
-----------------------------------------------------

11.いたづらする

ソースにいたづらをしよう。

vi mytest.c
-----------------------------------------------------
        len = spprintf(&strg, 0, "Congratulations! You have successfully modified ext/%.78s/config.m4. Module %.78s is now compiled into PHP.", "mytest", arg);

        ↓↓↓↓↓↓↓変更↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

        len = spprintf(&strg, 0, "さくらちゃんと結婚したい! Congratulations! You have successfully modified ext/%.78s/config.m4. Module %.78s is now compiled into PHP.", "mytest", arg);
-----------------------------------------------------

12 いたづらするする

出来たので男は黙ってコンパイルして実行。

make
php -d extension=modules/mytest.so  test.php

-----------------結果--------------------------------
さくらちゃんと結婚したい! Congratulations! You have successfully modified ext/mytest/config.m4. Module abc is now compiled into PHP.
-----------------------------------------------------

ぐはは。これで勝ったも同然。(何と戦っているんだ)

13.魔改造

関数を追加してみよう。


mytest_mahou_syoujyo関数を追加する。
2つのファイルを編集する。 mytest.c と php_mytest.h だ。

vi mytest.c
------------------------------------------------------------
/* {{{ mytest_functions[]
 *
 * Every user visible function must have an entry in mytest_functions[].
 */
const zend_function_entry mytest_functions[] = {
        PHP_FE(confirm_mytest_compiled, NULL)           /* For testing, remove later. */
        PHP_FE(mytest_mahou_syoujyo,    NULL)           /* For moemoe chun. ←追加追加追加追加 */  
        {NULL, NULL, NULL}      /* Must be the last line in mytest_functions[] */
};


/* 以下全部追加! */
PHP_FUNCTION(mytest_mahou_syoujyo)
{
        char *arg = NULL;
        int arg_len, len;
        char *strg;

        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) == FAILURE) {
                return;
        }
        if ( strcmp(arg,"さくら") == 0)
        {
                len = spprintf(&strg, 0,"はにゃーん");
        }
        else
        {
                len = spprintf(&strg, 0,"さくら %s ぢゃないもんっ",arg);
        }

        RETURN_STRINGL(strg, len, 0);
}

------------------------------------------------------------

ヘッダーファイルにも追加するよ。
忘れないでね!

vi php_mytest.h
------------------------------------------------------------
PHP_FUNCTION(confirm_mytest_compiled);  /* For testing, remove later. */
PHP_FUNCTION(mytest_mahou_syoujyo);     /* 追加追加追加追加追加追加追加 */
------------------------------------------------------------

14.人間だったら実行するはず

コンパイルして実行したっていいぢゃない。だって人間だもの。
こんどはワンライナーで試してみる。

make

php -d extension=modules/mytest.so  -r 'echo mytest_mahou_syoujyo("abc");'
----------------結果-----------------------------------------
さくら abc ぢゃないもんっ
-------------------------------------------------------------

php -d extension=modules/mytest.so  -r 'echo mytest_mahou_syoujyo("さくら");'
----------------結果-----------------------------------------
はにゃーん
-------------------------------------------------------------

やったー☆
さくらちゃん拡張できたよー♪♪♪♪

15 感激する。

ばよえーん


終わり。