私たちは、C / C ++とその仕組みを知らずにPHPの拡張機能(7.0.7)を作成しています

理論を勉強するのに多くの時間を必要とする特別な知識なしに、私のモジュール(拡張)をPHPに書くことは可能ですか? PHP自体でプログラミングする方法を知っていれば、特にPHPを使用すると開発中の拡張機能のフレームワークを生成し、その中でコードを記述することができるため、最も単純なCコードを書くことは難しくありません。 この質問に対しては、いまだにマシュマロが人気を集めています。 この出版物は、表面的な研究のみを目的として、PHPのソースコードを掘り下げ、その内部を少し見ることにした人々を対象としています。 現時点では、必要な知識がなくても同じことを検討しています。 PHPのインタビューでは、多くの場合、 階乗カウントコードの作成を求められます。 このような関数をCで記述し、PHPコードから呼び出すことができます。 私自身が行った行動を説明すると同時に、最初から何も知らない。 インターネットでは、この問題に関する多くの記事を見つけることができます。それらのほとんどは、zvalの「古い」形式を使用して情報を説明していますが、自分で追加することも悪くないと思います。



PHPには、拡張機能の将来のテンプレート(ワイヤーフレーム)を生成する既製のツール./ext_skel(extフォルダーにあります)があります。 それらによって生成されるすべてとその理由を説明するのではなく(それについて何も理解せず、自分自身も何も知らない)、単にタスクが解決する最小限の編集を書き留めます。 プロセス全体はCentOS 7で行われます。



将来のmathstat拡張のフレームワークを作成します。これには、階乗()関数が含まれます。



[root@localhost ext]# ./ext_skel --extname=mathstat ,     mathstat. [root@localhost mathstat]# ls config.m4 config.w32 CREDITS EXPERIMENTAL mathstat.c mathstat.php php_mathstat.h tests
      
      







create extensionコマンドを実行すると、次のサポート情報が表示されます。



 To use your new extension, you will have to execute the following steps: 1. $ cd .. 2. $ vi ext/mathstat/config.m4 3. $ ./buildconf 4. $ ./configure --[with|enable]-mathstat 5. $ make 6. $ ./sapi/cli/php -f ext/mathstat/mathstat.php 7. $ vi ext/mathstat/mathstat.c 8. $ make
      
      







PHP7では、生成後のbuildconfファイルはありません(おそらくこれらは以前のバージョンのPHPの残骸です)が、拡張機能のコンパイルはphpizeコマンドで始まることを知っています。 彼女は必要な./configureがあるファイルの束を「作成」します。 拡張機能のコンパイルのカスタムバージョンは、次のコマンドを順番に実行することで構成されていることを思い出してください。



 Phpize -> ./configure -> make -> make test -> make install
      
      







この一連のコマンドをすぐに実行すると、明らかな理由でmake installが中断し、コピーのエラーが発生します。 誰かが知っているなら、なぜそうなのかをコメントに書き留めてください。



 [root@localhost eugene]# make install Installing shared extensions: /usr/local/lib/php/extensions/no-debug-non-zts-20151012/ cp: cannot stat 'modules/*': No such file or directory make: *** [install-modules] Error 1
      
      







Phpizeは、config.m4の説明に基づいてファイルを作成します。 私が理解しているように、これは拡張機能が何であるか、外部ソースをプルアップするかどうかなどを説明する一種の宣言的な方法です...したがって、ソース内の他のPHP拡張機能を見て、ゼロからコンパイルエラーを最小限に抑えるためにできるだけ単純化することにしましたシート。 私は原則に基づいて行動します-「私はすべてのチェックマークを外します。」



このファイル(config.m4)を開き、このテキストのみを残します。 オプション「--enable-mathstat」は、これは単に外部ソース(ライブラリ)のない拡張機能であり、オンまたはオフにできることを示しています。 (dnlは行をコメントすることを意味します)



 dnl $Id$ PHP_ARG_ENABLE(mathstat, whether to enable mathstat support, [ --enable-mathstat Enable mathstat support]) if test "$PHP_MATHSTAT" != "no"; then PHP_NEW_EXTENSION(mathstat, mathstat.c, $ext_shared,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1) fi
      
      







phpizeコマンドを再起動します。



 [root@localhost mathstat]# phpize Configuring for: PHP Api Version: 20151012 Zend Module Api No: 20151012 Zend Extension Api No: 320151012 [root@localhost mathstat]# ls acinclude.m4 config.guess configure EXPERIMENTAL mathstat.c php_mathstat.h aclocal.m4 config.h.in configure.in install-sh mathstat.php run-tests.php autom4te.cache config.m4 config.w32 ltmain.sh missing tests build config.sub CREDITS Makefile.global mkinstalldirs
      
      







次に、使い慣れたコマンドを作成します。



 ./configure && make
      
      







テストを作成-最初に作成したテストを実行します。 これらのPHPテストについて私は何らかの形ですでに簡単に書いています。



 [root@localhost mathstat]# make install Installing shared extensions: /usr/local/lib/php/extensions/no-debug-non-zts-20151012/
      
      







今回は「make install」に合格し、php.iniに拡張機能を登録しようとします。



php.iniの場所を決定します。



 [root@localhost mathstat]# php --ini Configuration File (php.ini) Path: /usr/local/lib Loaded Configuration File: /usr/local/lib/php.ini Scan for additional .ini files in: (none) Additional .ini files parsed: (none) viim /usr/local/lib/php.ini extension=mathstat.so ;zend_extension = /usr/local/lib/php/extensions/no-debug-non-zts-20151012/xdebug.so [root@localhost mathstat]# systemctl restart php-fpm [root@localhost mathstat]# php -m | grep -i math mathstat
      
      







php -mコマンド(インストールされているすべてのモジュールを調べる)は、すべてが正常であるように見え、mathstat拡張機能がロードされていると言います。



現在のディレクトリでmathstat.phpテストファイルを実行します



 [root@localhost mathstat]# php mathstat.php Functions available in the test extension: confirm_mathstat_compiled Congratulations! You have successfully modified ext/mathstat/config.m4. Module mathstat is now compiled into PHP. [root@localhost mathstat]#
      
      







素晴らしい、何かがすでに機能しています。



2.階乗()関数の実装を開始します。



mathstat.cファイルを編集して、階乗()関数を追加します。



これを行うには、mathstatの「リスト」に関数を追加し、マクロを使用してスタブを作成します。 他の拡張機能と同様に、すべてを類推して行います。



 const zend_function_entry mathstat_functions[] = { PHP_FE(confirm_mathstat_compiled, NULL) /* For testing, remove later. */ PHP_FE(factorial, NULL) PHP_FE_END /* Must be the last line in mathstat_functions[] */ };
      
      







スタブ関数の実装。 マクロラッパーで作成。 最終的にどのように機能するかはまだ明確ではありません。将来のために研究を自分に任せます。 同様の形式で行うだけです。



 PHP_FUNCTION(factorial) { RETURN_LONG(1000); }
      
      





この場合、返されるデータのタイプごとに、独自のバージョンはRETURN_です。 インターネットで検索すると、可能なすべてのオプションが表示されます。 私たちには全体的な意味があります。 ここではすべてがシンプルに思えます。



次に、make clean && make && make installを繰り返します



 [root@localhost mathstat]# make clean find . -name \*.gcno -o -name \*.gcda | xargs rm -f find . -name \*.lo -o -name \*.o | xargs rm -f find . -name \*.la -o -name \*.a | xargs rm -f find . -name \*.so | xargs rm -f find . -name .libs -a -type d|xargs rm -rf rm -f libphp.la modules/* libs/* Build complete. Don't forget to run 'make test'. [root@localhost mathstat]# make install Installing shared extensions: /usr/local/lib/php/extensions/no-debug-non-zts-20151012/ [root@localhost mathstat]# systemctl restart php-fpm [root@localhost mathstat]# systemctl status php-fpm ● php-fpm.service - The PHP FastCGI Process Manager Loaded: loaded (/usr/lib/systemd/system/php-fpm.service; enabled; vendor preset: disabled) Active: active (running) since Thu 2016-06-16 01:12:22 EDT; 5s ago Main PID: 32625 (php-fpm) CGroup: /system.slice/php-fpm.service ├─32625 php-fpm: master process (/usr/local/etc/php-fpm.conf) ├─32626 php-fpm: pool www └─32627 php-fpm: pool www Jun 16 01:12:22 localhost.localdomain systemd[1]: Started The PHP FastCGI Process Manager. Jun 16 01:12:22 localhost.localdomain systemd[1]: Starting The PHP FastCGI Process Manager...
      
      







php-fpmを再起動しても、何かが壊れていることは示されなかったため、拡張機能で関数の存在をテストしてください。 念のため、コンパイルに合格しても。



 [root@localhost mathstat]# php mathstat.php Functions available in the test extension: confirm_mathstat_compiled factorial Congratulations! You have successfully modified ext/mathstat/config.m4. Module mathstat is now compiled into PHP.
      
      





関数の名前が表示され、さらに、PHPコードから既に呼び出すことができます。



 [root@localhost mathstat]# php -a Interactive mode enabled php > echo factorial(1); 1000 php >
      
      







関数が以前に指定された値1000を呼び出して返したことがわかります。



引数を受け取り、それを渡すように関数に教えます。このため、関数の引数の説明を作成する必要があります。 PHPの他の拡張機能の類似点を調べます(bcmathを見ました)。 マクロの束ですが、形式は原則として理解可能です。



 ZEND_BEGIN_ARG_INFO(arginfo_factorial, 0) ZEND_ARG_INFO(0, number) ZEND_END_ARG_INFO()
      
      







そして、その使用を機能に追加します。 NULLのままにすると、デフォルトはint型の引数型と見なされます。



 /* {{{ mathstat_functions[] * * Every user visible function must have an entry in mathstat_functions[]. */ const zend_function_entry mathstat_functions[] = { PHP_FE(confirm_mathstat_compiled, NULL) /* For testing, remove later. */ PHP_FE(factorial, arginfo_factorial) PHP_FE_END /* Must be the last line in mathstat_functions[] */ };
      
      



関数の本体をわずかに修正します。



 PHP_FUNCTION(factorial) { int argc = ZEND_NUM_ARGS(); long number = 0; if (zend_parse_parameters(argc, "l", &number) == FAILURE) { RETURN_LONG(0); } RETURN_LONG(number); }
      
      







zend_parse_parametersを使用します。これは、引用符( "")で囲まれた形式を使用して、渡された型の引数をチェックし、受け入れられた値をアドレスに設定します。 詳細はインターネットで簡単に見つけることができます。 階乗を実装するタスクについては、大きな知識はまだ必要ありません。



再コンパイル後に確認します(make clean && make && make install)。



 [root@localhost mathstat]# php -r "echo factorial('80');"; 80[root@localhost mathstat]# php -r "echo factorial(80);"; 80[root@localhost mathstat]#
      
      







引数に文字列を渡すと、エラーが発生します。 実際にこれが最後までどのように機能するかはまだ明確ではありませんが、必要なタスクは完了しています。



 [root@localhost mathstat]# php -r "echo factorial('aaaa');"; PHP Warning: factorial() expects parameter 1 to be integer, string given in Command line code on line 1 PHP Stack trace: PHP 1. {main}() Command line code:0 PHP 2. factorial() Command line code:1 Warning: factorial() expects parameter 1 to be integer, string given in Command line code on line 1 Call Stack: 0.2040 349464 1. {main}() Command line code:0 0.2040 349464 2. factorial() Command line code:1
      
      







関数の本体は充実しているように見えるため、ここで階乗計算アルゴリズム自体を実装します。 ご存知のように、アルゴリズムは再帰呼び出しに基づいています。同じことを行います。 関数compute()の本体を、後続の呼び出しで同じファイルmathstat.cに書き込みます。



 static long calculate(long number) { if(number == 0) { return 1; } else { return number * calculate(number - 1); } } PHP_FUNCTION(factorial) { int argc = ZEND_NUM_ARGS(); long number = 0; if (zend_parse_parameters(argc, "l", &number) == FAILURE) { RETURN_LONG(0); } number = calculate(number); RETURN_LONG(number); }
      
      





コンパイル、再起動、確認します。



 [root@localhost mathstat]# php -a Interactive mode enabled php > echo factorial(1); 1 php > echo factorial(2); 2 php > echo factorial(3); 6 php > echo factorial(4); 24 php > echo factorial(5); 120
      
      







驚くべきことに、これは機能します。 PHPですべてがどのように配置されているかについての基本的な知識がなく、C / C ++言語自体が大学から見えなかったため、この関数を実装するには3〜4時間しかかかりませんでした。 コードを記述するプロセス全体は、PHPの何らかのフレームワークでの作業に似ています。 ここで必要なのは、フレームワークとそのAPIのアーキテクチャを研究し、そのフレームワーク内で作業することだけです。



説明されているオプションには特に大きなコードはありませんが、githubへリンクを残します



All Articles