PHP拡張開発(1):入門

13954 ワード

PHP拡張に関する記事、ブログが多くなりました。
  • TIPIプロジェクト(http://www.php-internals.com/、強く推奨)
  • 『Extensding and Embodding PHP』(中国語の翻訳はhttp://www.walu.cc/phpbook/を見て、強く推薦します)
  • の「PHPコア技術と最適な実践」にはPHPの開発に特化した一章がありますが、バージョンは古いので、参考にしてください。
  • の「PHP 5権威ガイド」にもPHPの拡張開発を専門に行っている章があります。
  • このシリーズのブログでPHPの開発に関する学習と悟りをまとめ、Linuxシステムの下開発でPHPの拡張に必要な基本的な知識を簡単に明確に説明したいと思います。レベルが低いので、間違いがあります。指摘してください。
     
     
    準備工作
    まずPHPのソースコードを取得します。(Githubから最新の安定版をダウンロードしてもいいです。)そしてコンパイルします。コンパイル速度を速めるためには、すべての拡張機能を無効にすることを推奨していますが、Debug(enaber-debugオプションを使用して)とスレッドセキュリティ(enable-mantainer-ztsを使用して)を開いてください。
    $ ./buildconf --force
    
    $ ./configure --disable-all --enable-debug --enable-maintainer-zts
    
    $ make
    注意してください。私たちはprefixオプションを指定していません。必要ではないからです。注意出力情報を確認してください。依頼のカバンを取り付けてPHPのコンパイルに成功するかもしれません。
    コンパイル後のPHPの実行可能なプログラムはソースのsapiディレクトリの下で、異なる宿主環境に対応して、サブディレクトリがあります。これからは主にcliを使って環境を整えます。別名で便利です。
    $ alias php-dev=/usr/local/src/php-5.6.5/sapi/cli/php
    いくつかのコマンドラインのオプションがあります。
    php-dev -h          #       
    
    php-dev -v          #       
    
    php-dev --ini        #               
    
    php-dev -m          #          
    
    php-dev -i          # phpinfo
    
    php-dev -r <code>      #   code    
     
     
    骨組みを広げる
    PHPのすべての公式拡張はソースのextディレクトリの下にあります。自分で書いた拡張もカタログの下に置いてもいいです。このカタログの下にext_という名前があります。skyelのshellスクリプトはPHP拡張骨格を生成するために使われています。このスクリプトを使って、PHP拡張を素早く作成してくれます。
    $ ./ext_skel --extname=myext
    上の命令は私達にmyextという拡張子を作成してくれました。ソースはmyextディレクトリの下にあります。パラメータなしでスクリプトを実行するとヘルプ情報が印刷されます。このようにスクリプトが提供するオプションをより多く見ることができます。
    次に私達の拡張を完成させます。myextディレクトリに入り、config.m 4配置ファイルを編集し、PHP_を見つけます。アルゴ.ENABLEマクロ関数は、前のdnlコメントを削除します。ソースのルートディレクトリに戻して、再度buildconf、configureとmake命令を実行します。
    $ ./buildconf --force
    
    $ ./configure --help | grep myext
    
        --enable-myext           Enable myext support
    
    $ ./configure --disable-all --enable-myext --enable-debug --enable-maintainer-zts
    
    $ make
    注意してください。私達は使用しています。/configre--help grep myextで私達の拡張のロード状況をプリントしました。下の出力が見えないなら、私達の拡張は配置されていません。後でconfig.m 4ファイルを確認します。
    今回のコンパイルはとても速いはずです。ほとんどのコードはコンパイルされましたから。PHPは他にも拡張をコンパイルする方法があります。(動的接続を使用して、拡張を.soのファイルにコンパイルします。)しかし、拡張を開発する時はスタティックコンパイルを使用することをおすすめします。このように配置ファイルに拡張をロードするステップを省きます。
    すべてがうまくいけば、私たちの最初の拡張はもう実行できます。
    $ php-dev -m | grep myext
    
    myext
    
    $ php-dev -r 'echo confirm_myext_compiled("myext") . "
    ";
    ' Congratulations! You have successfully modified ext/myext/config.m4. Module myext is now compiled into PHP.
    最初のコマンドは、拡張がロードされていることを示します。二つ目のコマンドはext_を実行しました。skyel拡張骨格は自動的に私達のために作成された関数です。もちろん、この関数は意味がないですが、簡単にこの関数をハローワールドに変えられます。
     
     
    拡張機能の手動作成
    ほとんどの教程はext_である。skyelは骨格を拡大して原型のために開発のを述べて、このような方法はもちろんとても便利です。しかし、私は個人的には純粋な手作業開発の広がり方が好きです。このようにして、各細部を理解しやすくなります。
    手動で拡張を作成し、まずextディレクトリに進み、私達の拡張ディレクトリmyext 2を作成します。いくつかのファイルが必要です。config.m 4、myext 2.cとphp_myext 2.h
    まず、プロファイルconfig.m 4を作成します。
    PHP_ARG_ENABLE(myext2, whether to enable myext2 support,
    
    [  --enable-myext2           Enable myext2 support])
    
    
    
    if test "PHP_MYEXT2" != "no"; then
    
       PHP_NEW_EXTENSION(myext2, myext2.c, $ext_shared)
    
    fi
    config.m 4は、atoconfプログラムで使用されるプロファイルであり、atoolsツールボックスの中で重要な構成である。atootconfの使い方を完全に紹介するには時間がかかりますが、ここの使い方はとても簡単です。
    PHP_アルゴ.ENABLEはPHPがat confのために定義されたマクロ関数であり、myxt 2はその最初のパラメータであり、拡張された名前を指摘している。後の二つのパラメータは、makeとconfigureの実行時に表示されるだけですので、私達は自由に書いてもいいです。[]atootconf文法での役割は、二重引用符と似ています。文字列を包むために用いられます。また、4つ目のパラメータで拡張のデフォルトがオンかオフかを指定します。デフォルトはNOです。
    次の3行はshell文法です。PHP_を開いているかどうかを判断します。MYXT 2拡張モジュールです。この拡張モジュールを開けたら(--enable-myext 2)、PHP_MYXT 2変数の値はNOではないので、PHP_を実行します。NEW_EXTENSIONマクロです。このマクロ関数はPHPがatoconfのために定義されている拡張文法であり、最初のパラメータは同じ拡張名である。二つ目のパラメータは拡張してコンパイルするCファイルです。複数があれば順次書き込めばいいです。三つ目のパラメータは固定されています。shared
    次にphp_を作成しますmyxt 2.hヘッダファイルの名前はPHP拡張の仕様です。拡張子.h:
     1 #ifndef PHP_MYEXT2_H
    
     2 #define PHP_MYEXT2_H
    
     3 
    
     4 extern zend_module_entry myext2_module_entry;
    
     5 #define phpext_myext2_ptr &myext2_module_entry
    
     6 
    
     7 #define PHP_MYEXT2_VERSION "0.1.0"
    
     8 
    
     9 /* prototypes */
    
    10 PHP_FUNCTION(hello);
    
    11 
    
    12 #endif  /* PHP_MYEXT2_H */
    ここの主なコードはphpextという名前を定義しています。myext 2_ptrのマクロ、PHP下部はこのマクロを通じて私達の拡張を引用します。このマクロの名前は同じです。標準的なphpext_。拡張子_ptrmyext 2_module_entryは後で私達がCファイルの中で定義する構造体で、その名前も規範の─拡張子_です。module_entry
    また、拡張されたバージョン番号を示すマクロと関数プロトタイプを定義しました。FUNCTIONマクロ、PHP_FNCTIONマクロ関数のパラメータは外部で使用可能な関数名です。後でこの関数を実現します。
    最後にmyxt 2.cファイルの実現を見にきました。
     1 #include "php.h"
    
     2 #include "php_myext2.h"
    
     3 
    
     4 /* {{{ myext2_functions[]
    
     5  *
    
     6  * Every user visible function must have an entry in myext2_functions[].
    
     7  */
    
     8 static const zend_function_entry myext2_functions[] = {
    
     9     PHP_FE(hello,       NULL)
    
    10     PHP_FE_END
    
    11 };
    
    12 /* }}} */
    
    13 
    
    14 /* {{{ myext2_module_entry
    
    15  */
    
    16 zend_module_entry myext2_module_entry = {
    
    17     STANDARD_MODULE_HEADER,
    
    18     "myext2",               /* module name */
    
    19     myext2_functions,       /* module functions */
    
    20     NULL,                   /* module initialize */
    
    21     NULL,                   /* module shutdown */
    
    22     NULL,                   /* request initialize */
    
    23     NULL,                   /* request shutdown */
    
    24     NULL,                   /* phpinfo */
    
    25     PHP_MYEXT2_VERSION,     /* module version */
    
    26     STANDARD_MODULE_PROPERTIES
    
    27 };
    
    28 /* }}} */
    
    29 
    
    30 #ifdef COMPILE_DL_MYEXT2
    
    31 ZEND_GET_MODULE(myext2)
    
    32 #endif
    
    33 
    
    34 /* {{{ proto void hello()
    
    35    Print "hello world!" */
    
    36 PHP_FUNCTION(hello)
    
    37 {
    
    38     php_printf("hello world!
    "); 39 } 40 /* }}} */
    スケルトンを拡張して作成した.cファイルを比較すると,我々のcファイルは非常に簡単であるが,これらは基本的な拡張にとって十分であることがわかった。
    上のコードは簡単で明瞭です。ほとんどの注釈は既に説明的です。簡単に要約します。
  • の先頭には、私たちが使用するヘッダファイルが含まれています。php.hは必要です。私たちが使う標準ライブラリのほとんどのファイルを含んでくれました。例えばstdio.h、stdlib.hなどです。
  • myext 2_functionsは、私たちが露出したい関数からなる構造体配列を定義しています。各元素はPHP_を通しています。FEマクロ指定。PHP_FEマクロには二つのパラメータがあります。一つ目は外部で使用できる関数名です。二つ目はパラメータ情報です。最後の要素はPHP_でなければなりません。FE_ENDその注釈に注意して、外部に露出して使用する関数は、必ず構造体配列に定義されていることを改めて強調します。
  • myext 2_module_entryは私たちのモジュール情報を定義しています。それは構造体で、ほとんどの属性は注釈によって説明されています。真ん中の5つの関数の指針に注意してください。私たちは簡単にNULLに置いて、後のブログでそれらの使い方を説明します。
  • ZEEND_GET_MODULE(myext 2)マクロ関数はifdefマクロに含まれているので、それが呼出されるかどうかは状況によって決まります。どのような場合に呼び出しられますか?
  • 最後の数行のコードはhello関数を実現しました。簡単です。php_を呼び出します。printf出力ハローワールド!改行符とphp_printfの使い方はprintfと全く同じです。
  • コメントの中の{と}は、vimなどのエディタをたたむために使うもので、コメントを書くのもオススメです。
  • この中にはPHP_などのマクロが含まれています。FE,PHP_FE_END,PHP_FUNCTIONなど、これらのマクロを今後のブログに紹介してこそいいです。今の一番簡単な方法はこれらのマクロを覚えておくことです。
    私たちはそれぞれのファイルの名前、変数の名前、スペース、インデント、コメントなどが非常に標準的であり、これらの仕様に従って、私たちが作成したコードとPHP自身のコードをよりよく一致させることができます。このような仕様でPHP拡張を開発することもお勧めします。
    最後に、コンパイルは私たちの拡張機能を実行します。
    $ ./buildconf --force
    
    $ ./configure --help | grep myext2
    
      --enable-myext2           Enable myext2 support
    
    $ ./configure --disable-all --enable-myext2 --enable-debug --enable-maintainer-zts
    
    $ make
    
    
    
    $ php-dev -m | grep myext2
    
    myext2
    
    $ php-dev -r 'hello();'
    
    hello world!