PHP ネイティブ インターフェイス
PHP ネイティブ インターフェイス (PNI) は、PHP コードがネイティブ アプリケーション (ハードウェアおよびオペレーティング システム プラットフォームに固有のプログラム) および C、C++、およびその他の言語で書かれたライブラリを呼び出したり、ネイティブ アプリケーションから呼び出されたりできるようにする PHP 拡張機能です。アセンブリ..
Java Native Interface (JNI) に似ています。
PNI を使用すると、アプリケーション全体を PHP 言語で作成できない場合に、プログラマがネイティブ コードを使用できるようになります。ネイティブ コードの使用を決定する一般的な状況は次のとおりです。
PHPer の皆さんはご存知のように、これは伝統的な方法です。 PHP 拡張機能を作成する C/C++ を呼び出します。ただし、PNI には複数のメリットがあります:
新しい PHP 拡張機能をインストールまたは更新するとき、特に PHP クラスターの運用中に PHP サービスが再起動されるリスクがあります。しかし、PNI を使用すると、ローカル インターフェイス ライブラリを変更するだけです。
PHP 拡張機能の開発と比較して、ネイティブ C/C++ を記述するのと同じようにネイティブ インターフェイスを開発します。
開発者は、 PHP-API、Zend-API、または PHP 拡張フレームワークはもうありません。データ型と PNI フレームワークがよりシンプルになりました。
PHP-API と Zend API もネイティブ インターフェイスで利用可能です。
ネイティブ インターフェイスを増やしても、現在の PHP サービスには影響しません。
// file pni_math.c#include<math.h>#include "php.h"/* * double pow(double x, double y); */zval *PNI_pow(zval **args) { // every PNI function returns zval(php variable) , the paramters are in the args double x,y,z; zval *tmp = NULL; zval *res = NULL; tmp = args[0]; x = Z_DVAL_P(tmp); // get the double value via Z_DVAL_P tmp = args[1]; y = Z_DVAL_P(tmp); // Why we write it like this instead of `y = Z_DVAL_P(args[1]);`? It's a C Trap. z = pow(x,y); // ALLOC_INIT_ZVAL(res); // It's essential to init return value unless the return value is NULL. ZVAL_DOUBLE(res, z); // Use ZVAL_DOUBLE to assign the result to the return variable, the data type is double. return res;}
php-ni -lm -o libpnimath.so pni_math.c
// file testPni.php<?phptry { $pni = new PNI('libpnimath.so'); var_dump($pni->PNI_pow(2.0,6.0)); $noPni = new PNI('/unexisted/library.so'); var_dump($pni->unDefinedFunction(2.0,6.0));} catch (PNIException $e) { var_dump($e->getMessage()); var_dump($e->getTraceAsString());}
$ php testPni.php
以下のような出力です
float(64)string(154) "Dlopen /unexisted/library.so error (/unexisted/library.so: cannot open shared object file: No such file or directory), dl handle resource is not created."string(69) "#0 /root/pni.php(5): PNI->__construct('/unexisted/libr...')#1 {main}"
すべての演算子マクロは Zend API で定義されています。
Z_LVAL_P(zval_p) // get Long(no int)Z_BVAL_P(zval_p) // get BooleanZ_DVAL_P(zval_p) // get DoubleZ_STRVAL_P(zval_p) // get char *Z_STRLEN_P(zval_p) // get the length of a string / Long
したがって、PNI 関数の戻り変数は zval です。まず、ALLOC_INIT_ZVAL(res) を使用して初期化する必要があります。そして、それに値を割り当てます。
ZVAL_NULL(z) // assign NULLZVAL_LONG(z, l) // assign LONGZVAL_STRING(z, s, duplicate) //assign a string/char * . Duplicate ? allways be 1.ZVAL_STRINGL(z, s, l, duplicate) //assign a string with fixed length. Duplicate ? the same as above.ZVAL_FALSE(z)ZVAL_TRUE(z)ZVAL_BOOL(z, boolean) // ZVAL_BOOL(z, 1) and ZVAL_TRUE(z) are the same.Likely, ZVAL_BOOL(z, 0) and ZVAL_FALSE(z) are the same.
Zend API や PHP API について詳しく知る必要はありません。上記で参照したものはすべて、PHP コードと C コード間の単純な通信を実現するのに十分です。
git clone https://github.com/zuocheng-liu/pni.git
cd <src-pni>phpize./configuremake && make install
php.iniに以下の行を追加します
extension=pni.so;
service php-fpm restart // cgi modeapachectl restart // sapi mode // do nothing in cli mode
PNI への貢献は、新機能、バグ修正、または単なるバグ レポートのプル リクエストの形で高く評価されます。
PNI のコードは、PHP ライセンスのバージョン 3.01 の条件に基づいて配布されます。(ライセンスを参照)