ext_skelを使用してPHP拡張機能を実装します

ext_skelを使用してPHP拡張機能を実装します

 

1.前に書く

この記事はPHP7.4 、PHP拡張機能を最初から作成する方法に基づいています。この記事では、主に拡張機能を作成するための基本的な手順について説明します。この例では、次の関数を実装します。

<?phpecho hello();?> 12345

出力内容:

$ php74 ./hello.php 

$ hello word123

hello メソッド呼び出したhello 後、拡張機能にメソッドを実装します hello word!

2つ目は、コードを生成する

PHPには、基本的なコードを生成するためのツールext_skel.phpが用意されています。このツールは、PHPのソースコードphp-对应版本/ext/ディレクトリにあります。

extディレクトリ

コマンドを入力 php ext_skel.php --ext_skel.php --ext hello --author sunct --stdすると、次のような効果があります。

$ php ext_skel.php ext_skel.php --ext hello --author sunct--std構成
スクリプトの
コピー...完了ソースのコピー...完了
テストのコピー...完了

成功。これで、拡張機能をコンパイルする準備が整いました。そのためには、使用して
次のステップを:

CD /パス/に/ PHP-srcが/ハロー
は、phpize 
./configureを
作り

、コンパイルが完了するとDOはテストを実行することを忘れないで:
メイクテストは

!PHPを使用していただきありがとうございます12345678910111213141516171819を

パラメータ--ext追加せずに直接実行するphp ext_skel.phpError、エラーが報告されます。

$ php ext_skel.php 
エラー:拡張子名が渡されていません。「-ext <name>」を使用してください1234

extディレクトリには、下に生成される helloディレクトリ。

[外部リンク画像の転送に失敗しました。元のサイトにホットリンク防止メカニズムがある可能性があります。画像を保存して直接アップロードすることをお勧めしますこんにちはディレクトリ
。PHP拡張機能は、すべての拡張機能に共通の複数のファイルで構成されています。これらのファイルの詳細の多くは、異なる拡張子間で類似していますが、各ファイルの内容をコピーするのに手間がかかります。幸い、PHP 4.0以降に配布されている、ext_skelという名前のすべての初期化作業を実行できるスクリプトがあります。

以下は、ソースパッケージ内のjson ファイル内容です

ソースjsonディレクトリ

オプションのパラメータ:

オプション

  phpext_skel.php --ext <name> [--experimental] [--author <name>] 
                   [--dir <path>] [--std] [--onlyunix] 
                   [--onlywindows] [- help] 

  --ext <name> <name>として定義された拡張機能の名前// <name>として定義された拡張機能
  --experimentalこの拡張機能が実験的な場合に渡さ
                        れ、拡張機能のルートにEXPERIMENTALファイルが作成され ます//この拡張子が実験的なものである場合は、拡張子のルートディレクトリにあるEXPERIMENTALファイルを使用します
  --author <name>あなたの名前。これは--stdが渡された場合に使用され、   
                        CREDITSファイルの場合は//あなたの名前(渡された場合)-std、 CREDITSファイルは、この名前を使用しますこのスクリプトは、どこのディレクトリにデフォルト
                        住んでいます
  --dir <path>拡張子が必要なディレクトリへのパス
                        作成した。デフォルトは、このスクリプトが配置されているディレクトリです
  --std渡さ
                        れると、コアに含まれる拡張機能で使用される標準ヘッダーが使用され
  ます
  --onlyunixUnixの構成スクリプトのみを生成します--onlywindowsWindowsの構成スクリプトのみを生成します
  --helpこのヘルプ12345678910111213141516171819

一般的に、新しい拡張機能を開発する場合、関係するパラメーターは --ext name 合計のみ --helpです。拡張機能の構造に既に精通している場合を除き、このパラメーターを指定すると、ext_skelは生成されたファイル内の多くの有用なコメントを省略しません。
残りの--ext名は、拡張子の名前を渡し ext_skelます。「名前」は1つで全为小写字母的标识符、含まれているだけ で、字母和下划线PHP配布パッケージのext/フォルダーにあります 唯一

3、config.m4構成ファイルを変更します

拡張config.m4ファイルは、サポートされている拡張構成オプション、必要な拡張ライブラリ、およびその一部としてコンパイルするソースファイルをUNIXビルドシステムに通知します。PHP固有のautoconf組み込みマクロを含む、頻繁に使用されるすべてのautoconfマクロ用。

config.m4の役割は、phpizeツールを使用して構成ファイルを生成することです。構成ファイルは、環境の検出に使用されます。拡張機能のコンパイルと実行に必要な環境が満たされているかどうかを確認してください。ここで、config.m4ファイルの変更を開始します。

config.m4ファイル

その中で、dnlはコメント記号です。

上記のコードは、作成する拡張機能が他の拡張機能またはlibライブラリに依存している場合、PHP_ARG_WITH関連するコードのコメントを解除する必要があることを示しています。それ以外の場合は、PHP_ARG_ENABLE 関連するコードセグメントのコメントを解除し ます。私たちが書く拡張機能は、他の拡張機能やlibライブラリに依存する必要はありません。したがって、PHP_ARG_ENABLE前のコメントを削除します。

上記の図が生成されたとき、他の拡張子に依存しないことが指定されています。

4、コードの実装

hello.cファイルを変更します。helloメソッドを実装します。

実行中 php ext_skel.php --ext hello に、hello.cファイルは2つのテストメソッドを生成しました:hello_test1hello_test2

ファイル生成コード:

/ * {
   
  {
   
  {void hello_test1()
 * / PHP_FUNCTION(hello_test1){ 
	ZEND_PARSE_PARAMETERS_NONE(); 

	php_printf( "拡張子%sが読み込まれ、機能しています!\ r \ n"、 "hello");} / *}}} * // * { 
  
  {
   
  {string hello_test2([string $ var])
 * / PHP_FUNCTION(hello_test2 ){ 
	char * var = "World"; 
	size_t var_len = sizeof( "World")-1; 
	zend_string * retval; 

	ZEND_PARSE_PARAMETERS_START(0、1)
		Z_PARAM_OPTIONAL Z_PARAM_STRING(var、var_len)
	ZEND_PARSE_PARAMETERS_END(); 

	retval = strpprintf(0、 "Hello%s"、var); 

	RETURN_STR(retval);} 123456789101112131415161718192021222324252627

その中で:

関数hello_test1() 出力の実行は、The extension hello is loaded and working!パラメーターを渡すことができないかecho hello_test1('这是一个参数');、エラーを報告できません警告:PHP Warning: hello_test1() expects exactly 0 parameters, 1 given in /Users/sunct/code/php/hello.php on line 2;

実行関数hello_test2() はを出力Hello Worldし、関数はパラメータを渡すことができますhello_test2('这是一个参数')、出力:Hello 这是一个参数

hello 関数をモデル化して、関数の後に置くことができ ますPHP_FUNCTION(hello_test2)

/ *新しい関数* / PHP_FUNCTION(hello){ 
     zend_string * strg; 
     strg = strpprintf(0、 "hello word"); 
     RETURN_STR(strg);} 12345678

出力に使用 hello word

PHP_FE_ENDを見つけて、上記のコードを追加します。

PHP_FE(hello、NULL)1

写真が示すように:

ここに画像の説明を挿入

5、コンパイルしてインストール

cd hello / 
phpize 
./configure  
make1234

phpize実行後のファイル結果

./configureの実行後のファイル結果

それらの中で:
./configureあなた自身の環境に従ってパラメータを追加してください。

私が使用するテストを容易にするために:./configure --prefix=/usr/local/php7 --without-iconv --with-apxs2 --enable-fpm --with-config-file-path=/usr/local/php7/etc;

php.iniファイルを変更し、次のコードを追加します。

拡張= say.so1

実施した:

php -m1

php-m実行結果

表示されない場合hello、現在のPHPを使用すると、次の警告エラーが表示されます。

PHP警告:PHPスタートアップ:ダイナミックライブラリ 'hello.so'を読み込めません(試行:/usr/local/php7/lib/php/extensions/no-debug-non-zts-20190902/hello.so(dlopen(/ usr /local/php7/lib/php/extensions/no-debug-non-zts-20190902/hello.so、9):画像が見つかりません)、/ usr / local / php7 / lib / php / extensions / no-debug- non-zts-20190902 / hello.so.so(dlopen(/usr/local/php7/lib/php/extensions/no-debug-non-zts-20190902/hello.so.so、9):画像が見つかりません) )行01の不明

これは、/usr/local/php7/lib/php/extensions/no-debug-non-zts-20190902/hello.so ファイルが存在しないことを示していますhello.so生成されたファイルをここに手動で移動できます。
コンパイルと実行を開始すると、hello 生成されたmodulesフォルダーの下にフォルダーが生成されます。hello.so
helloフォルダ内のモジュール

ファイルに移動:

sudo cp〜 / code / php / php-7.4.13 / ext / hello / modules / hello.so /usr/local/php7/lib/php/extensions/no-debug-non-zts-20190902/hello.so1

phpinfo()を表示:

ここに画像の説明を挿入
ここに画像の説明を挿入

6、テストを呼び出す

PHPファイルを作成し、helloメソッドを呼び出します。出力コンテンツが期待を満たしているかどうかを確認します。

結果は次のとおりです。

<?php echo "\ r \ n実行hello()----:"。hello(); echo "\ r \ n実行hello_test2()----:"。hello_test2(); echo "\ r \ nExecutehello_test2 ( 'これはパラメータです')----: "。hello_test2( 'これはパラメータです'); echo" \ r \ n実行hello_test1()----: "。hello_test1(); 12345

ここに画像の説明を挿入

セブン、※ファイルを分析する

1、config.m4

UNIXビルドシステム構成

2、config.w32

Windowsビルドシステム構成

3、php_hello.h

拡張機能を静的モジュールとしてPHPバイナリファイルにビルドする場合、ビルドシステムは、拡張モジュール構造へのポインターの宣言を含む拡張機能名の前に、php_がヘッダーファイルを追加することを期待します。他のヘッダーと同様に、このファイルには通常、他のマクロ、プロトタイプ、およびグローバル変数が含まれています。

4、hello.c

メインの拡張ソースファイル。慣例により、ファイル名は拡張子ですが、これは必須ではありません。このファイルには、モジュール構造宣言、INIエントリ、管理機能、ユーザースペース機能、およびその他の拡張機能の要件が含まれています。

PHP拡張機能のメインソースファイルには、Cプログラムの構造が含まれています。これらの中で最も重要なのはzend_module構造体です。これは、新しい拡張機能を作成するときの最初の連絡先です。この構造には、Zend Engine拡張機能の依存関係、バージョン、コールバック、その他の重要なデータを伝える多くの情報が含まれています。

/ * {
   
  {
   
  {hello_module_entry 
 * / zend_module_entry hello_module_entry = { 
	STANDARD_MODULE_HEADER、
	"hello"、/ *拡張子名* / 
	hello_functions、/ * zend_function_entry * / 
	NULL、/ * PHP_MINIT-モジュールの初期化* / 
	NULL、/ * PHP_MSHUTDOWN-モジュールのシャットダウン* / 
	PHP_RINIT(hello)、/ * PHP_RINIT-初期化要求* / 
	NULL、/ * PHP_RSHUTDOWN-シャットダウン要求* / 
	PHP_MINFO(hello)、/ * PHP_MINFO-モジュール情報* / 
	PHP_HELLO_VERSION、/ *バージョン* / 
	STANDARD_MODULE_PROPERTIES}; / *} }} * / 123456789101112131415

モジュール構造フィールド値

フィールド 説明
サイズ[^ 1] [^ 1] [^ 2] [^ 3] sizeof(zend_module_entry) 構造体のバイトサイズ。
zend_api [^ 1] [^ 2] [^ 3] ZEND_MODULE_API_NO このモジュールの対象となるZendAPIバージョン。
zend_debug [^ 1] [^ 2] [^ 3] ZEND_DEBUG モジュールがデバッグをオンにしてコンパイルされているかどうかを示すフラグ。
zts [^ 1] [^ 2] [^ 3] USING_ZTS モジュールがZTS(TSRM)を有効にしてコンパイルされているかどうかを示すフラグ(メモリ管理を参照)。
ini_entry [^ 1] [^ 3] ヌル Zendはこのポインタを内部的に使用して、モジュールによって宣言されたINIエントリへの非ローカル参照を維持します。
deps [^ 3] ヌル モジュールの依存関係のリストへのポインター。
名前 「mymodule」 モジュールの名前。これは、「spl」や「standard」などの略語です。
関数 mymodule_functions モジュール関数テーブルへのポインターであるZendは、このポインターを使用して、モジュール内の関数をユーザースペースに公開します。
module_startup_func PHP_MINIT(mymodule) モジュールが最初にPHPの特定のインスタンスにロードされたときにZendが呼び出すコールバック関数。
module_shutdown_func PHP_MSHUTDOWN(mymodule) 通常、最終シャットダウン中のコールバック関数であるZendは、モジュールが特定のPHPインスタンスからアンロードされたときにこの関数を呼び出します。
request_startup_func PHP_RINIT(mymodule) Zendは、各リクエストの開始時にコールバック関数を呼び出します。この関数を呼び出すとすべてのリクエストにコストがかかるため、この関数はできるだけ短くするか、空にする必要があります。
request_shutdown_func PHP_RSHUTDOWN(mymodule) Zendが各リクエストの最後に呼び出すコールバック関数。この関数を呼び出すとすべてのリクエストにコストがかかるため、この関数はできるだけ短くするか、空にする必要があります。
info_func PHP_MINFO(mymodule) `phpinfo()`関数が呼び出されたときにZendが呼び出すコールバック関数。
バージョン NO_VERSION_YET モジュール開発者によって指定された、モジュールバージョンを示す文字列。バージョン番号は、 `version_compare()`で期待される形式(たとえば、「1.0.5-dev」)またはCVSまたはSVNリビジョン番号(たとえば、「$ Rev:322138 $」)を採用することをお勧めします。
globals_size [^ 1] [^ 4] [^ 5] [^ 6] sizeof(zend_mymodule_globals) モジュールのグローバル変数を含むデータ構造のサイズ(存在する場合)。
globals_id_ptr [^ 1] [^ 4] [^ 5] [^ 6] [^ 7] &mymodule_globals_id USING_ZTS定数が真であるかどうかに応じて、これら2つのフィールドの1つだけが存在します。前者はTSRM割り当てテーブル内のモジュールのグローバル変数のインデックスであり、後者はグローバル変数への直接のポインタです。
globals_ptr [^ 1] [^ 4] [^ 5] [^ 6] [^ 8] &mymodule_globals_id
globals_ctor [^ 4] [^ 5] [^ 6] PHP_GINIT(mymodule) この関数は、 `module_startup_func`の前にモジュールのグローバル変数を初期化するために呼び出されます。
globals_dtor [^ 4] [^ 5] [^ 6] PHP_GSHUTDOWN(mymodule) この関数は、 `module_shutdown_func`の後にモジュールのグローバル変数を解放するために呼び出されます。
post_deactivate_func [^ 4] ZEND_MODULE_POST_ZEND_DEACTIVATE_N(mymodule) この関数は、リクエストが閉じられた後にZendによって呼び出されます。めったに使用されません。
module_started [^ 1] [^ 9] [^ 4] 0 これらのフィールドは、Zendの内部追跡情報に使用されます。
タイプ[^ 1] [^ 9] [^ 4] 0
ハンドル[^ 1] [^ 9] [^ 4] ヌル
module_number [^ 1] [^ 9] [^ 4] 0

[^ 1]このフィールドはモジュール開発者には適用されません。
[^ 2]このフィールドはSTANDARD_MODULE_HEADER_EX埋められます。
[^ 3]このフィールドはSTANDARD_MODULE_HEADER埋められます。
[^ 4]このフィールドはSTANDARD_MODULE_PROPERTIES埋められます。
[^ 5]このフィールドはNO_MODULE_GLOBALS埋められます。
[^ 6]このフィールドはPHP_MODULE_GLOBALS埋められます。
[^ 7] USING_ZTSがtrueの場合のみ、このフィールドはtrueです。
[^ 8] USING_ZTSがの場合のみ、このフィールドはfalseになります。
[^ 9]このフィールドはSTANDARD_MODULE_PROPERTIES_EX埋められます。

おすすめ

転載: blog.csdn.net/yy17822307852/article/details/113018868