ホームページ  >  記事  >  バックエンド開発  >  Linux での PHP 拡張機能開発シリーズ: 2. 典型的な拡張機能開発_PHP チュートリアル

Linux での PHP 拡張機能開発シリーズ: 2. 典型的な拡張機能開発_PHP チュートリアル

WBOY
WBOYオリジナル
2016-07-20 11:14:08713ブラウズ

序文で述べた内容をいくつか読めば、PHP 拡張機能の開発について一般的に理解できるはずです。実際には、この記事ではそうではありません。をロールに組み込み、最初の拡張機能を開発しました。


1. PHP をコンパイルします

開発前に、PHP ソースコードを準備してコンパイルする必要があります。プロセスは次のとおりです。 リーリー

私はphp5.3.9を使用しています。解凍後、PHPソースコードディレクトリに入り、php.iniを直接コンパイルして追加しました。 リーリー

他の拡張機能は静的にコンパイルしませんでしたが、後で使用するデバッグをオンにしました。次に、php.ini 内の対応する項目を変更します。ここでは詳しく説明しません。

ここで、後で多くの作業を節約するために、PHP 関連の情報を環境変数に追加します。

リーリー

私は root を使用し、他の別のユーザーは対応するユーザー ディレクトリ内の .bask_profile ファイルを変更し、次のようにファイル内の PATH の後に /usr/local/webserver/php/bin/ を追加します。

リーリー

環境変数が設定されたので、PHPのバージョンを確認してみましょう:

OK、コンパイル作業は完了しました。続行しましょう。

2. 一般的な開発プロセス

典型的な拡張機能の開発プロセスは以下のとおりです:

3. 拡張関数の定義

-2147483648 から 2147483647

、32 ビット システムと同じ。

4. 公式開発

リーリー

次に、スケルトンを生成するために PHP が提供する拡張スケルトン ツール ext_skel について学習します。 ext_skel の使用方法は次のとおりです。 リーリー

今回は 2 つのオプションを使用します。 --extname=myip は拡張機能の名前を定義し、 --proto=myip.pro は拡張機能の関数プロトタイプを定義します。 まず、拡張機能の関数プロトタイプを生成します。ファイル:

リーリー

次のコンテンツを追加します:

リーリー

これは、拡張機能に int を返し、文字列を入力として受け取る関数があることを意味します。

この時点で、次のコマンドを実行して拡張スケルトンを生成します:

リーリー

OK、この時点で、現在の PHP 拡張ディレクトリの下にサブディレクトリ myip が生成されていることがわかります。myip と入力して見てください:

リーリー

以下に示すように、生成された一連のファイルが見つかります:

この時点で、2 番目のステップに進むことができます。

2. config.m4 を変更します

config.m4 ファイルの機能については、後の記事で詳しく説明することにします。ここでは、何をするのかだけ説明します。

vim を使用して config.m4 を編集します:

リーリー

次のように、16 ~ 18 行目の先頭にある dnl を削除します。

これを行う具体的な理由については、後の記事で説明します。ここでは、config.m4 を直接終了して保存し、次のステップに進みます。

3. エンコーディング

メインイベントはここです。ついに myip.c に入って関数をコーディングできるようになります。一緒に乾杯しましょう! リーリー 下の写真に示されている場所を見つけてください:

この図は、提供された関数プロトタイプに基づいて拡張スケルトン ツールによって生成された対応する関数を示しています。ここで注意すべき点がいくつかあります。

1. PHP_FUNCTION: PHP コアによって定義されるマクロであり、ZEND_FUNCTION と同じであり、実際に生成される関数名は zif_ip2long32 です。

2. zend_parse_parameters: PHP は弱く型指定された言語であり、C は強く型指定された言語であるため、この関数を使用して PHP によって渡されたパラメーターを受け取り、特定の型変換を実行して PHP 変数を PHP 変数を認識できるものに変換する必要があります。 C言語のタイプ。

zend_parse_parameters 関数のプロトタイプは次のとおりです:

リーリー

パラメータの説明:

  •       num_args:传递给函数的参数个数。通常的做法是使用宏 ZEND_NUM_ARGS()。
  •       TSRMLS_CC:线程安全,总是传递TSRMLS_CC宏。 详解:http://www.54chen.com/php-tech/what-is-tsrmls_cc.html
  •       type_spec:第三个参数是一个字符串,指定了函数期望的参数类型
  •       ...:需要随参数值更新的变量列表]

  • type_spec是格式化字符串,其常见的含义如下: 参数   代表着的类型 b   Boolean l   Integer 整型 d   Floating point 浮点型 s   String 字符串 r   Resource 资源 a   Array 数组 o   Object instance 对象 O   Object instance of a specified type 特定类型的对象 z   Non-specific zval 任意类型~ Z   zval**类型 f   表示函数、方法名称

   我们将该函数修改为如下内容:

<span  PHP_FUNCTION(ip2long32)
 {
         </span><span char</span> *ip =<span  NULL;
         </span><span int</span> argc =<span  ZEND_NUM_ARGS();
         </span><span int</span><span  ip_len;
 
         </span><span if</span> (zend_parse_parameters(argc TSRMLS_CC, <span "</span><span s</span><span "</span>, &ip, &ip_len) ==<span  FAILURE) {
                 </span><span return</span><span ;
         }
         
         int32_t ip_int32;
         unsigned </span><span char</span><span  ip1, ip2, ip3, ip4;
         
         sscanf(ip, </span><span "</span><span %hhu.%hhu.%hhu.%hhu</span><span "</span>, &ip1, &ip2, &ip3, &<span ip4);
         ip_int32 </span>= (int32_t)((ip1 << <span 24</span>) | (ip2 << <span 16</span>) | (ip3 << <span 8</span>) |<span  ip4);
         RETURN_LONG(ip_int32);
 }</span>

    功能完成了,这边有个RETURN_LONG(ip_int32)比较特殊,这也是PHP内核提供的宏,用于返回值给PHP,具体说明如下:

设置返回值并且结束函数        设置返回值             宏返回类型和参数
RETURN_LONG(l)           RETVAL_LONG(l)           整数
RETURN_BOOL(b)          RETVAL_BOOL(b)           布尔数(1或0)
RETURN_NULL()           RETVAL_NULL()           NULL
RETURN_DOUBLE(d)        RETVAL_DOUBLE(d)        浮点数
RETURN_STRING(s, dup)       RETVAL_STRING(s, dup)       字符串。如果dup为1,引擎会调用estrdup()重复s,使用拷贝。如果dup为0,就使用s
RETURN_STRINGL(s, l, dup)     RETVAL_STRINGL(s, l, dup)    长度为l的字符串值。与上一个宏一样,但因为s的长度被指定,所以速度更快。
RETURN_TRUE           RETVAL_TRUE            返回布尔值true。注意到这个宏没有括号。
RETURN_FALSE           RETVAL_FALSE           返回布尔值false。注意到这个宏没有括号。
RETURN_RESOURCE(r)        RETVAL_RESOURCE(r)       资源句柄。

    编码完成了,保存并退出,然后我们可以开始编译了。

    4. 编译

<span phpize
.</span>/configure --with-php-config=/usr/local/webserver/php/bin/php-<span config
</span><span make</span> && <span make</span> <span install</span>

    不出意外的话编译完成后会有如下提示:

Installing shared extensions:     /usr/local/webserver/php/lib/php/extensions/debug-non-zts-<span 20090626</span>/

    进入该目录看下是否已经有myip.so,有的话最后我们就可以修改php.ini载入该so文件

    5. 修改php.ini

cd /usr/local/webserver/php/<span lib
vim php.ini</span>

    修改extension_dir,并加入 extension = myip.so

extension_dir = "/usr/local/webserver/php/lib/php/extensions/debug-non-zts-20090626/"<span 
extension </span>= myip.so

    退出保存,并重启php,如果是使用Phpfpm的话可以执行如下命令:

<span kill</span> -USR2 `<span cat</span> /usr/local/webserver/php/var/run/php-fpm.pid`

    看下扩展是否正常载入:

[root@tm977 lib]# php -m|<span grep</span><span  myip
myip</span>

    说明已经正常载入了,最后我们测试下扩展函数吧!

    6. 测试

php -r <span "</span><span var_dump(ip2long32('192.168.1.1'));</span><span "</span>
<span int</span>(-<span 1062731519</span><span )
php </span>-r <span "</span><span var_dump(ip2long('192.168.1.1'));</span><span "</span>  
<span int</span>(<span 3232235777</span>)

    如上所示,ip2long32输出的是32位有符号整数,而ip2long输出的是64位无符号整数,大功告成!

 

五、小结

www.bkjia.comtru​​ehttp://www.bkjia.com/PHPjc/440319.html技術記事序文で述べた内容をいくつか読めば、PHP 拡張機能の開発について一般的に理解できるはずです。拡張機能の開発は面倒で複雑だと考える人もいるかもしれませんが、実際はそうではありません。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。