php 拡張機能の開発
1. 概要
PHP 拡張機能は、データベース アクセス、シリアル化、リモート プロシージャ呼び出しなど、PHP を拡張する主な手段です。PHP を使用したことのある人は、PHP の多くの機能も拡張機能を通じて実装されています。ソース コードには数十の拡張機能が含まれており、PECL ウェアハウスにも数百の拡張機能が提供されているため、PHP を使用して開発する限り、PHP 拡張機能の開発は避けられません。この記事では、PHP 拡張機能の開発方法を画像とテキストを使用して段階的に紹介します。
開発環境: Ubuntu 10.10、PHP 5.3.5、PHP を実行できる Web サーバー (Nginx または Apache)
要件: C 言語と PHP プログラミングの基本を理解している
要件: fetion_echo という名前の拡張機能を開発します。これには単純なsay_goodbye() 関数のみがあり、文字列を入力すると、関数は「Goodbye xxx」を返します。
PHP 拡張機能の開発プロセスは、基本的に次のステップに分けることができます: ?
1. 拡張フレームワークを生成します?
2. Unix ビルド システムの構成?
3. phpinfo() コールバック関数を作成します ?
4. コアコードを書く?
5. 設定とコンパイル?
6. php.ini を設定します
2. 拡張フレームワークを生成します
PHP ソース コードをダウンロードします。私は PHP 5.3.5 を使用しています。 PHP ソース コード ディレクトリに入ると、PHP 拡張機能に関連する ext ディレクトリがあることがわかります。ls コマンドを使用してそれを表示すると、pdo_mysql、json などの多くの既存の PHP 拡張機能が表示されます。図 1 に示す:
このディレクトリには ext_skel スクリプト ファイルがあることに注意してください。次に、これを使用して Linux 環境で PHP 拡張コード フレームワークを生成します。ext_skel_win32.php は Windows での生成スクリプトです。ext_skel の完全なコマンド形式は次のとおりです:
./ext_skel --extname=module [--proto=file] [--stubs=file] [--xml[=file]]<code>./ext_skel --extname=module [--proto=file] [--stubs=file] [--xml[=file]]<br>
[--skel=dir] [--full-xml] [--no-help]
[--skel=dir] [--full-xml] [--no-help]
パラメータは次のように説明されます: ?
--extname: パラメーターは拡張機能 ? の名前を指定します。
--no-help: 生成されたコード フレームワークにコメントなどを追加しないように指定します。PHP 拡張機能の開発に十分な経験がない限り、このパラメーターを指定しないでください。当面は他のパラメータを考慮する必要はありません。
次に、ext ディレクトリに次のコマンドを入力します:
$ ./ext_skel --extname=fetion_echo
再度 ls コマンドを使用して ext ディレクトリを表示すると、fetion_echo という名前の追加ディレクトリがあることがわかります。図に示すように、ext_skel によって PHP 拡張機能の基本フレームワークが確立されていることがわかります。 2:
ここには、紹介する必要がある重要なファイルがいくつかあります: ?
config.m4: Linux でのビルド システム構成ファイル。構成ファイルとメイクファイルの生成に使用されます。 ?
php_fetion_echo.h: 拡張モジュールのヘッダー ファイル。 ?
fetion_echo.c: 拡張モジュールのメイン プログラム ファイル。拡張モジュールに複数の関数がある場合、最終的にすべての関数エントリがこのファイルに含まれます。
3. Unix ビルド システムの構成
config.m4 ファイルは、拡張機能がサポートする設定オプションを Unix ビルド システムに伝えます。ファイルを開くには、見慣れない設定が多数表示されますが、ファイルは " で始まるので、心配しないでください。 dnl」 冒頭の内容は単なるコメントなので、今は考えないでください。次の行のみを使用できます:
dnl 拡張機能が外部のものを参照する場合は、次のように使用します。<code>dnl If your extension references something external, use with:<br>
dnl PHP_ARG_WITH(fetion_echo, for fetion_echo support,<br>
dnl Make sure that the comment is aligned:<br>
dnl [ --with-fetion_echo Include fetion_echo support])<br>
dnl Otherwise use enable:<br><span style="color: #ff0000;">dnl PHP_ARG_ENABLE(fetion_echo, whether to enable fetion_echo support,<br>
dnl Make sure that the comment is aligned:<br>
dnl [ --enable-fetion_echo Enable fetion_echo support])</span>
dnl PHP_ARG_WITH(fetion_echo、fetion_echo サポートの場合、
dnl コメントが整列していることを確認してください:
dnl [ --with-fetion_echo fetion_echo サポートを含める])
dnl それ以外の場合は、enable を使用します:dnl PHP_ARG_ENABLE(fetion_echo, fetion_echo サポートを有効にするかどうか,
dnl コメントが整列していることを確認してください:
dnl [ --enable-fetion_echo fetion_echo サポートを有効にする])PHP_ARG_ENABLE(fetion_echo, whether to enable fetion_echo support,<br>
Make sure that the comment is aligned:<br>
[ --enable-fetion_echo Enable fetion_echo support])<span class="Apple-converted-space">?</span>
コード>
実際、拡張機能で外部参照を使用する場合は次の 3 行を使用し、それ以外の場合は最後の 3 行を使用することは誰でも理解できます。単純なエコー拡張機能を開発しているだけであり、外部参照は使用しないため、コメントを解除するだけです。最後の 3 行:
PHP_ARG_ENABLE(fetion_echo, fetion_echo サポートを有効にするかどうか,<br>
コメントが揃っていることを確認してください:
[ --enable-fetion_echo fetion_echo サポートを有効にする])?
コード>
設定ファイルを保存して終了します。
/* {{{ fetion_echo_module_entry */<br>
zend_module_entry fetion_echo_module_entry = {<br>
#if ZEND_MODULE_API_NO >= 20010901<br>
STANDARD_MODULE_HEADER,<br>
#endif<br>
"fetion_echo",<br>
fetion_echo_functions,<br>
PHP_MINIT(fetion_echo),<br>
PHP_MSHUTDOWN(fetion_echo),<br>
PHP_RINIT(fetion_echo),<br>
PHP_RSHUTDOWN(fetion_echo),<br>
PHP_MINFO(fetion_echo),<br>
#if ZEND_MODULE_API_NO >= 20010901<br>
"0.1",<br>
#endif<br>
STANDARD_MODULE_PROPERTIES<br>
};
4. PHP 拡張コア コードの分析
以下に、PHP 拡張機能のコア コードを簡単に紹介します。fetion_echo.c ファイルを開くと、次のコードが表示されます。
/* {{{ fetion_echo_module_entry */
zend_module_entry fetion_echo_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
STANDARD_MODULE_HEADER、
#endif
"フェションエコー"、
fetion_echo_functions、
PHP_MINIT(fetion_echo)、
PHP_MSHUTDOWN(fetion_echo)、
PHP_RINIT(fetion_echo)、
PHP_RSHUTDOWN(fetion_echo)、
PHP_MINFO(fetion_echo),
#if ZEND_MODULE_API_NO >= 20010901
"0.1"、
#endif
STANDARD_MODULE_PROPERTIES
};コード>
C 言語の構造体はここで初期化されます。各 PHP 拡張機能は実際には zend_module_entry 構造体であり、zend_module_entry ソース コードを見るとそれを確認できます。この例では、上記のコードを簡単に紹介します:
1. STANDARD_MODULE_HEADER: C 言語マクロ。構造体のサイズなどを含む、zend_module_entry の最初のいくつかのフィールドを初期化するために使用されます。
2. fetion_echo: 構造体 ? の名前フィールドに対応する拡張機能の名前を指定します。
3. fetion_echo_functions: 拡張関数テーブルを指す zend_function_entry タイプの配列。ユーザーに公開する必要があるすべての関数を関数テーブル ? に登録する必要があります。
4. PHP_MINIT(fetion_echo): 拡張機能のロード時に呼び出されるモジュール初期化コールバック関数、MINIT = モジュール初期化?
5. PHP_MSHUTDOWN(fetion_echo): 拡張カップがアンインストールされるときに呼び出されるモジュール アンインストール コールバック関数、MSHUTDOWN = モジュール シャットダウン?
6. PHP_RINIT(fetion_echo): 各リクエストの開始時に呼び出されるリクエスト初期化コールバック関数、RINIT = 初期化リクエスト?
7. PHP_RSHUTDOWN(fetion_echo): 各リクエストの最後に呼び出されるリクエスト終了コールバック関数、RSHUTDOWN = シャットダウンリクエスト?
8. PHP_MINFO(fetion_echo): phpinfo() 関数で呼び出される、モジュールのカスタム情報を表示するために使用される拡張情報関数 ?
9. 0.1: ? 構造体のバージョン フィールドに対応する拡張バージョン番号を指定します。
10. STANDARD_MODULE_PROPERTIES: C 言語マクロ。zend_module_entry の最後のいくつかのフィールドを初期化するために使用されます。
ご覧のとおり、4 ~ 8 では 4 つのコールバック関数を指定しました。これらの 4 つの関数は、重要なポイントでリソースを初期化したり、リソースをリサイクルしたりできる注入メカニズムを提供すると言えます。さらに、すべてのコールバック関数は、主に PHP 実行時の名前の競合を防ぐために、Zend が提供するマクロを通じて定義されていることに注意してください。実際には、関数の戻り値やグローバル変数も含まれます。全員がこの方法を使用します。
5. phpinfo() コールバック関数を作成します ?
fetion_echo.c ファイルを開き、PHP_MINFO_FUNCTION に次のコードを記述します。
PHP_MINFO_FUNCTION(fetion_echo) {<code>PHP_MINFO_FUNCTION(fetion_echo) {<br>
php_info_print_table_start();<br>
php_info_print_table_header(2, "fetion_echo support", "enabled");<br><span style="color: #ff0000;">php_info_print_table_row(2, "author", "TerryLee");<br>
php_info_print_table_row(2, "version", "0.1");</span>
<br>
php_info_print_table_end();<br>
/* Remove comments if you have entries in php.ini<br>
DISPLAY_INI_ENTRIES();<br>
*/<br>
}
php_info_print_table_start();
php_info_print_table_header(2, "fetion_echo support", "enabled");php_info_print_table_row(2, "author", "TerryLee");
php_info_print_table_row(2, "バージョン", "0.1");
php_info_print_table_end();
/* php.ini にエントリがある場合はコメントを削除します
DISPLAY_INI_ENTRIES();
*/
}コード>
ここでは主に phpinfo() 関数が呼び出されたときにカスタム情報を表示するために、次の 4 つの関数が使用されます。
1. php_info_print_table_start(): phpinfo テーブルの開始を定義します ?
2. php_info_print_table_header(): phpinfo テーブルのヘッダーを定義します。最初のパラメーターに列数を指定し、その後に最初のパラメーターの数に等しいカスタム テキスト情報を指定します。
3. php_info_print_table_row(): phpinfo テーブルの内容を定義します。最初のパラメーターは列の数を指定し、その後に最初のパラメーターの数に等しいカスタム テキスト情報を指定します。
4. php_info_print_table_end(): phpinfo テーブルの終わりを定義します
この例では、拡張機能が利用可能かどうかを指定するテーブル ヘッダーと、拡張機能の作成者とバージョンを指定する 2 行のコンテンツを定義します。
6. コアコードを書く
次に、拡張コア コードを作成します。php_fetion_echo.h ファイルを開き、宣言の行を追加します。
PHP_FUNCTION(say_goodbye);
これは C 言語関数を記述する「ネイティブ」な方法ではなく、PHP_FUNCTION マクロを通じて定義されていることに注意してください (具体的な理由は前述しました)。say_goodbye は、C 言語関数に公開するために開発した拡張モジュールの関数名です。ユーザー。
fetion_echo.c を開いて、say_goodbye 関数をここに実装します。
PHP_FUNCTION(say_goodbye) {<code>PHP_FUNCTION(say_goodbye) {<br>
char *arg = NULL;<br>
int arg_len, len;<br>
char *strg;<br>
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s",<br>
&arg, &arg_len) == FAILURE) {<br>
return;<br>
}<br>
len = spprintf(&strg, 0, "Goodbye %sn", arg);<br>
RETURN_STRINGL(strg, len, 0);<br>
}
char *arg = NULL;
int arg_len, len;
char *strg;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s",
&arg, &arg_len) == 失敗) {
戻る;
}
len = spprintf(&strg, 0, "さようなら %sn", arg);
RETURN_STRINGL(strg, len, 0);
}コード>
内部の具体的な実装は非常に単純で、パラメータを受け取った後、「Goodybye パラメータ」文字列を返します。
1. パラメーターの受信: ここでの受信関数のパラメーターは、zend_parse_parameter 関数を通じて解析する必要があります。最初のパラメーターは、ユーザーが Say_goodbye 関数に渡すパラメーターの数を指定します。これは、マクロ ZEND_NUM_ARGS( ) TSRMLS_CC はスレッドの安全性を確保するために使用されます。第 1 章 2 つのパラメータは文字列であり、各文字は型を表します。「s」は char* または int 型を表し、「b」は Boolean 型を表します。完全な型マッピングは後でここで確認できます。いくつかのパラメータは、受信パラメータ値を受け取るために定義したローカル変数です。
2. 関数の戻り値: C 言語のネイティブの return ステートメントを使用することはできません。たとえば、RETURN_STRINGL は文字列を返し、RETURN_TRUE はブール型の true を返します。
拡張関数パラメータ情報の宣言(はヘッダファイルに記述する必要があります)
)、関数のプロトタイプはsay_goodbye(name)、パラメータ宣言メソッドは次のとおりです:
ZEND_BEGIN_ARG_INFO(arg_say_goodbye, 0)<code>ZEND_BEGIN_ARG_INFO(arg_say_goodbye, 0)<br>
ZEND_ARG_INFO(0, name)<br>
ZEND_END_ARG_INFO()
ZEND_ARG_INFO(0, 名前)
ZEND_END_ARG_INFO()
Zend API が提供するマクロ定義は次のとおりです。拡張関数のパラメータ宣言については後ほど紹介します。 Say_goodbye 関数を実装した後、次のコードに示すように、関数テーブル fetion_echo_functions (前に紹介した) に関数を登録します。最初のパラメーターは関数名、2 番目のパラメーターは関数パラメーターの配列情報です。
const zend_function_entry fetion_echo_functions[] = {<code>const zend_function_entry fetion_echo_functions[] = {<br><span style="color: #ff0000;">PHP_FE(say_goodbye, arg_say_goodbye)<br>
{NULL, NULL, NULL}</span>
<br>
};
PHP_FE(say_goodbye, arg_say_goodbye)
{NULL、NULL、NULL}
};コード>
最後の行 {NULL, NULL, NULL} は必須であることに注意してください。関数テーブルに登録されている関数のみがユーザーに公開されます。
7. 設定、コンパイル、インストール
?
/usr/local/php5/bin/phpize
fetion_echo ディレクトリに次のコマンドを入力します。インストールした PHP パスに従って特定のパスを設定してください。
sudo apt-get install m4<br>
sudo apt-get install autoconf
m4 と autoconf がインストールされていない場合は、次のコマンドを使用して最初にインストールしてください。
sudo apt-get install m4
sudo apt-get install autoconf
phpize を実行した後、ls コマンドを使用すると、configure ファイルを含む多くのファイルが fetion_echo ディレクトリに生成されていることを確認できます。
この拡張機能は、Linux での「標準」の 3 ステップのインストール モードを使用して、以下のようにインストールできます。./configure <br>
或者: ./configure --with-php-config=/usr/local/php/bin/php-config<br>
make<br>
make install
./configure
または: ./configure --with-php-config=/usr/local/php/bin/php-config
作る
/etc/init.d/php-fpm restart
8. ? を実行します。
上記の手順を完了した後、phpinfo() を実行すると、以下が表示されるはずです。
次のように簡単なテスト スクリプトを作成します:
echo say_goodbye("Foo");
?>?
echo Say_goodbye("Foo");
?>?
コード>
ブラウザで表示:
このインターフェースが表示されれば、拡張機能は正常に動作しています。
9. 概要
この記事では、簡単な例を使用して、Zend API と C 言語を使用して Linux 上で PHP 拡張機能を開発する方法を紹介します。次の記事では、簡単なクラス拡張を開発する方法を見ていきます。
参考文献
1. http://www.php.net/manual/en/internals2.buildsys.configunix.php?