ホームページ > バックエンド開発 > PHPチュートリアル > PHPカスタム関数の呼び出しと実行処理の詳細説明

PHPカスタム関数の呼び出しと実行処理の詳細説明

伊谢尔伦
リリース: 2023-03-11 15:00:02
オリジナル
3946 人が閲覧しました

関数を呼び出すには、関数の名前、パラメーター、関数の定義 (つまり、関数の具体的な実行内容) など、いくつかの基本情報が必要です。関数が定義されていれば、この関数の名前は何なのか、呼び出し時にどのようなパラメータが渡されるのか、関数の動作内容は当然わかります。ただし、Zend エンジンは私たちと違って PHP ソース コードを「理解」することができません。コードを実行する前に処理する必要があります。次の 2 つの小さな例から始めましょう:

<?php
    function foo(){
        echo "I&#39;m foo!";
    }   
    foo();
?>
ログイン後にコピー

以下、対応する OPCODES を見てみましょう:

関数名: (null) line # * OP FETCH EXT 結果

オペランド


------ -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- --------------------- ---------------------------- ------------------------------------------- do_fcall fetch ext Returnオペランド

----------------------------------------------- ------------------------------ gt;次のセクションで詳しく説明するように、の実装は特に重要です。 ここで、関数 foo の呼び出しに注目してみましょう。 foo を呼び出すときの OPCODE は「DO_FCALL」です。DO_FCALL が関数呼び出し操作を実行すると、ZE は function_table 内の関数名に従って検索します (前述したように、ここでの関数名は str_to lower によって処理されるため、PHP の関数名は大文字と小文字が区別されません)。 -sensitive) 関数の定義が存在しない場合は、「未定義の関数 xxx() への呼び出し」というエラー メッセージが報告され、関数の zend_function 構造体ポインタが返されます。 function.type の関数は、関数が内部関数であるかどうかを判断するために使用されます。関数

もユーザー定義関数です。zend_execute_internal (zend_internal_function.handler) を呼び出すか、この関数に含まれる zend_op_array を実行するために zend_execute を直接呼び出します。


関数の実行

注意深い読者は、関数が呼び出されるとき、および上記のオペコードの関数定義に「関数名:」があることに気づくかもしれませんが、実際には、ユーザー定義関数
の実行は関係ありません。他のステートメントの実行との違いは、本質的には、関数内の PHP ステートメントが関数の外部の PHP ステートメントと変わらないことです。関数本体自体の最大の違いは、その実行環境にあります。 この「実行環境」の最も重要な機能は、変数のスコープです。ご存知のとおり、関数内で定義された変数を関数の外で直接使用することはできず、その逆も同様です。そして、関数を実行する際には、関数に入る前の環境情報を保存する必要があります。関数の実行後、これらの環境情報も復元され、プログラム全体が実行を継続できるようになります。

内部函数的执行与用户函数不同。用户函数是php语句一条条“翻译”成op_line组成的一个op_array,而内部函数则是用C来实现的,因为执行环境也是C环境, 所以可以直接调用。如下面的例子:

<?php
    $foo = &#39;test&#39;;
    print_r($foo);
?>
ログイン後にコピー

生成的opcodes中,内部函数和用户函数的处理都是由DO_FCALL来进行的。而在其具体实现的zend_do_fcall_common_helper_SPEC()中, 则对是否为内部函数进行了判断,如果是内部函数,则使用一个比较长的调用

((zend_internal_function *) EX(function_state).function)->handler(opline->extended_value, EX_T(opline->result.u.var).var.ptr, EX(function_state).function->common .return_reference?&EX_T(opline->result.u.var).var.ptr:NULL, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC);

上面这种方式的内部函数是在zend_execute_internal函数没有定义的情况下。而在而在Zend/zend.c文件的zend_startup函数中,

zend_execute_internal = NULL;

此函数确实被赋值为NULL。于是我们在if (!zend_execute_internal)判断时会成立,所以我们是执行那段很长的调用。 那么,这段很长的调用到底是什么呢?以我们常用的 count函数为例。在<<第一节 函数的内部结构>>中, 我们知道内部函数所在的结构体中 有一个handler指针指向此函数需要调用的内部定义的C函数。 这些内部函数在模块初始化时就以扩展的函数的形式加载到EG(function_table)。其调用顺序:

php_module_startup --> php_register_extensions --> zend_register_internal_module
--> zend_register_module_ex --> zend_register_functions

zend_register_functions(NULL, module->functions, NULL, module->type TSRMLS_CC)

在standard扩展中。module的定义为:

zend_module_entry basic_functions_module = {
    STANDARD_MODULE_HEADER_EX,
    NULL,
    standard_deps,
    "standard",                 /* extension name */
    basic_functions,            /* function list */
    ... //省略}
ログイン後にコピー

从上面的代码可以看出,module->functions是指向basic_functions。在basic_functions.c文件中查找basic_functions的定义。

以上がPHPカスタム関数の呼び出しと実行処理の詳細説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート