11.埋め込み式PHP

6340 ワード

PHPソースディレクトリ構造の紹介とPHPライフサイクルから分かるように、埋め込み式PHPはCLIに似ており、SAPIインタフェースのもう一つの実現でもある.一般的に、1つのリクエストのライフサイクルも他のSAPIと同じです.モジュール初期化=>リクエスト初期化=>処理リクエスト=>クローズリクエスト=>クローズモジュールです.もちろん、これは理想的な状況にすぎません.特定のアプリケーションは独自の特殊なニーズから、PHPスクリプトを処理する段階で基本的に一致しているだけです.
埋め込みPHPについては、理解が少ないか、まったく使えないか、ネット上の関連資料も多くないかもしれません.例えば、多くのゲームでLua言語を接着言語として使用したり、拡張ゲームのスクリプト言語として使用したりします.同様に、ブラウザのJavascript言語はブラウザに埋め込まれています.ただ、現在ではPHPを埋め込み言語として使用するアプリケーションは少なく、PHPの強みは現在もWeb開発にある.
PHPは埋め込み式PHPのサポートとPHPは埋め込み式にどのようなインタフェースや機能を提供していますか?まず、使用するソースコードの例を見てみましょう.
#include <sapi/embed/php_embed.h>
#ifdef ZTS
    void ***tsrm_ls;
#endif
/* Extension bits */
zend_module_entry php_mymod_module_entry = {
    STANDARD_MODULE_HEADER,
    "mymod", /* extension name */
    NULL, /* function entries */
    NULL, /* MINIT */
    NULL, /* MSHUTDOWN */
    NULL, /* RINIT */
    NULL, /* RSHUTDOWN */
    NULL, /* MINFO */
    "1.0", /* version */
    STANDARD_MODULE_PROPERTIES
};
/* Embedded bits */
static void startup_php(void)
{
    int argc = 1;
    char *argv[2] = { "embed5", NULL };
    php_embed_init(argc, argv PTSRMLS_CC);
    zend_startup_module(&php_mymod_module_entry);
}
static void execute_php(char *filename)
{
    zend_first_try {
        char *include_script;
        spprintf(&include_script, 0, "include '%s'", filename);
        zend_eval_string(include_script, NULL, filename TSRMLS_CC);
        efree(include_script);
    } zend_end_try();
}
int main(int argc, char *argv[])
{
    if (argc <= 1) {
        printf("Usage: embed4 scriptfile";);
        return -1;
    }
    startup_php();
    execute_php(argv[1]);
    php_embed_shutdown(TSRMLS_CC);
    return 0;
}

以上のコードは『Extending and Embedding PHP』の20章で見つけることができます(元のコードには記号の間違いがあり、興味のある子供靴は周りを見ることができます).上のコードは埋め込み式PHPドライバ(ドライバとして機能するでしょう)で、このドライバではPHPコードを実行できます.このコードには、PHP組み込みサポートの宣言、組み込みPHP実行環境の起動、PHPコードの実行、組み込みPHP実行環境の閉鎖が含まれています.次に、このコードについて、PHPが組み込みサポートに対してどのような仕事をしたかを分析します.まず、次の行を見てください.
#include <sapi/embed/php_embed.h>

sapiディレクトリの下のembedディレクトリはPHPが埋め込み型の抽象層である.ここでは、使用する関数またはマクロ定義があります.例で使用したphp_embed_init,php_embed_shutdownなどの関数.
2~4行目:
#ifdef ZTS
    void ***tsrm_ls;
#endif

ZTSはZend Thread Safetyの略で、これに関連してTSRM(スレッドセキュリティリソース管理)の東東があり、この後の章で詳しく説明しますが、ここでは説明しません.
6~17行目:
zend_module_entry php_mymod_module_entry = {
    STANDARD_MODULE_HEADER,
    "mymod", /* extension name */
    NULL, /* function entries */
    NULL, /* MINIT */
    NULL, /* MSHUTDOWN */
    NULL, /* RINIT */
    NULL, /* RSHUTDOWN */
    NULL, /* MINFO */
    "1.0", /* version */
    STANDARD_MODULE_PROPERTIES
};

以上のPHP内部のモジュール構成宣言では、ここでモジュールの初期化については、初期化要求等の関数ポインタがNULLとなっている.つまり、モジュールは、初期化及び終了要求等のイベントが発生したときに何も行わない.しかし、これらの操作はsapi/embed/php_embed.cファイルのphp_embed_shutdownなどの関数に現れます.モジュール構造の定義についてzend/zend_modules.h中.
startup_php関数:
static void startup_php(void)
{
    int argc = 1;
    char *argv[2] = { "embed5", NULL };
    php_embed_init(argc, argv PTSRMLS_CC);
    zend_startup_module(&php_mymod_module_entry);
}

この関数は2つの関数php_を呼び出します.embed_initとzend_startup_moduleは初期化作業を完了します.php_embed_init関数定義sapi/embed/php_embed.cファイルにあります.埋め込み式に対するPHPの初期化サポートが完了しました.zend_startup_module関数はPHPの内部API関数であり、定義されたモジュールを登録する役割を果たし、ここではmymodモジュールを登録する.この登録プロセスは定義されたzend_のみをmodule_entry構造は登録モジュールリストに追加されます.
execute_php関数:
static void execute_php(char *filename)
{
    zend_first_try {
        char *include_script;
        spprintf(&include_script, 0, "include '%s'", filename);
        zend_eval_string(include_script, NULL, filename TSRMLS_CC);
        efree(include_script);
    } zend_end_try();
}

関数名から見ると,この関数の機能はPHPコードを実行するものである.sprrintf関数を呼び出してinclude文を構築し、zend_を呼び出します.eval_string関数はこのinclude文を実行します.zend_eval_stringは最終的にzend_を呼び出すeval_stringl関数、この関数はフローがPHPコードをコンパイルし、zend_を生成するop_arrayタイプのデータを作成し、opcodeのプロセスを実行します.このプログラムは次のphpプログラムに相当します.このプログラムはphpコマンドで実行できます.次のプログラムは実際の意味がありませんが、埋め込みPHPでは、Cで実現されたシステムにPHPを埋め込み、PHPで機能を実現することができます.
<?php
if($argc < 2) die("Usage: embed4 scriptfile");

include $argv[1];
?>

main関数:
int main(int argc, char *argv[])
{
    if (argc <= 1) {
        printf("Usage: embed4 scriptfile";);
        return -1;
    }
    startup_php();
    execute_php(argv[1]);
    php_embed_shutdown(TSRMLS_CC);
    return 0;
}

この関数はメイン関数で、初期化操作を実行し、入力したパラメータに基づいてPHPのinclude文を実行し、最後にクローズ操作を実行し、戻ります.php_embed_shutdown関数定義sapi/embed/php_embed.cファイルにあります.PHPの組み込み型クローズ操作のサポートが完了しました.要求クローズ操作、モジュールクローズ操作などが含まれます.
以上はPHPの組み込み方式を用いて開発された簡単なPHPコードドライバであり、これらの呼び出しの方式はすべてPHP自体のいくつかの実現に基づいているが、組み込み型のSAPI定義は非常に簡単で、ApacheやCGIモードの複雑さがなく、あるいはかなり粗末であり、これもその環境によって決定される.組み込み環境では、多くのネットワークプロトコルに必要な方法は不要です.以下に示すように、組み込みモジュールを定義します.
sapi_module_struct php_embed_module = {
    "embed",                       /* name */
    "PHP Embedded Library",        /* pretty name */

    php_embed_startup,              /* startup */
    php_module_shutdown_wrapper,   /* shutdown */

    NULL,                          /* activate */
    php_embed_deactivate,           /* deactivate */

    php_embed_ub_write,             /* unbuffered write */
    php_embed_flush,                /* flush */
    NULL,                          /* get uid */
    NULL,                          /* getenv */

    php_error,                     /* error handler */

    NULL,                          /* header handler */
    NULL,                          /* send headers handler */
    php_embed_send_header,          /* send header handler */

    NULL,                          /* read POST data */
    php_embed_read_cookies,         /* read Cookies */

    php_embed_register_variables,   /* register server variables */
    php_embed_log_message,          /* Log message */
    NULL,                           /* Get request time */
    NULL,                           /* Child terminate */

    STANDARD_SAPI_MODULE_PROPERTIES
};
/* }}} */

この定義にはいくつかのNULl定義が見られ、前の節でSAPIについて述べたとき、クッキーの読み取りを例に挙げたが、ここでもクッキーの読み取りを実現するphp_embed_read_cookies関数ですが、この関数の実装は空のポインタNULLです.