3

PHP源码之宏【转载】

 2 years ago
source link: http://xwxz.github.io/php-source-macro-01/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

​ 作为 PHPer,我们几乎每天都在写函数,我们一定会好奇,那些 PHP 内置的函数,是长什么样子的。如果写过 PHP 扩展的话,一定知道这个宏:PHP_FUNCTION。在定义一个函数的时候,这样来使用这个宏。例如 array_change_key_case,它的定义是这样的:PHP_FUNCTION(array_change_key_case)。没错,就是这么简单。但是,在这个简单的背后,却没有这么简单。

PHP_FUNCTION 追根溯源

相信对这篇文章感兴趣的同学,一定多少对 C 语言以及它的宏定义有一定的了解。如果没有,也不要紧,我这里来简单解释一下,什么是宏。

C 语言中的宏,我认为,可以理解为一种简单的封装。通过宏定义,可以对开发者隐去一些细节,让开发者在使用简单的语法来完成重复的复杂的编码。当然,宏定义还有其它的用途,但是,我们在 PHP_FUNCTION 涉及到的就是这个作用。有下面的代码。

#define TEST(test) void test(int a)
TEST(haha)

宏,就是完全的替换,即使用后面的语句替换前面的。那么对于下面的 TEST(haha) 就相当于下面的样子。

void haha(int a)

PHP_FUNCTION 的定义

首先,我们要定义函数,这样使用这个宏。

PHP_FUNCTION(array_change_key_case)
{
// TODO
}

我们在 php-src/main/php.h 中找到了下面的定义。

#define PHP_FUNCTION ZEND_FUNCTION

也就是说,这里用 ZEND_FUNCTION 替换了 PHP_FUNCTION 这个宏。所以,我们的定义就相当于变成了这样。

ZEND_FUNCTION(array_change_key_case)
{
// TODO
}

我们继续往下找,因为,这里还是宏,我们并没有看到我们希望看到的代码。我们可以在 php-src/Zend/zend_API.h 中找到下面的定义。

#define ZEND_FN(name) zif_##name
#define ZEND_FUNCTION(name) ZEND_NAMED_FUNCTION(ZEND_FN(name))
#define ZEND_NAMED_FUNCTION(name) void name(INTERNAL_FUNCTION_PARAMETERS)

我们看到,在宏定义中,使用了另外的宏。不要怕,还是一个词,替换。我们按照这样的步骤来。(## 是一个连接符,它的作用是,是将它前面的与后面的,按照字符串的方式连接起来。

  1. 替换 ZEND_FUNCTION
ZEND_NAMED_FUNCTION(ZEND_FN(name))
{
// TODO
}
  1. 替换 ZEND_FN
ZEND_NAMED_FUNCTION(zif_array_change_key_case)
{
// TODO
}
  1. 替换 ZEND_NAMED_FUNCTION
void zif_array_change_key_case(INTERNAL_FUNCTION_PARAMETERS)
{
// TODO
}

到这里,我们可以看到,这里已经基本和我们熟悉的函数定义差不多了,不过,这还没完,以为,这里还有宏,那就是 INTERNAL_FUNCTION_PARAMETERS。我们找到 php-src/Zend/zend.h,可以找到 INTERNAL_FUNCTION_PARAMETERS的宏定义。

#define INTERNAL_FUNCTION_PARAMETERS zend_execute_data *execute_data, zval *return_value

好了,依然按照替换的原则,我们就可以将函数定义变成这样了。

void zif_array_change_key_case(zend_execute_data *execute_data, zval *return_value)
{
// TODO
}

看,整个函数的定义,已经完全没有宏了,这已经是我们在熟悉不过的 C 语言函数的定义了。这就是
PHP_FUNCTION 的整个定义的过程。

execute_data 和 return_value

return_value,顾名思义,就是定义的 PHP 函数的返回值。而 execute_data,按照我的理解,就是 Zend 内部的一个调用栈,而在执行这个函数的时候,指向的是这个函数的栈帧。具体的细节,暂时在这里先不考虑,有兴趣的同学可以来这里看一下

文章转载自segmentfault,原文地址:https://segmentfault.com/a/1190000010529733


Recommend

  • 37

    作者:暗灭链接:技术面试的时候该怎么样介绍自己?来源:知乎“不好意思,稍微打断一下,可以详细介绍一下自己的项目经历么?从入职时间开始,到离职,每一个项目的开始时间,团队人数,你负责的模块。”不要紧张。面试就是聊天,没底气的人,才会紧张。当然对于很...

  • 38

  • 39

    转载:“往后余生,向死而生”:一个38岁中年男人的心梗满月纪 - 来源:“于一条”微信号作者:一条我叫于冬,字一条,是一个在准二线城市工作和生活的38岁普通中年男人。认识我的朋友们,你们好。之所以写下这篇文章,是因为在刚刚过去的三月里,我经历了一场叫作“心...

  • 46
    • 掘金 juejin.im 5 years ago
    • Cache

    前端算法整理转载

    递归递归算法 : 英语:recursion algorithm)在计算机科学中是指一种通过重复将问题分解为同类的子问题而解决问题的方法。绝大多数编程语言支持函数的自调用,在这些语言中函数可以通过调用自身来进行递归。递归的两个要素:调用自身能跳出循环阶乘n! =

  • 25

    职场话题 - @vanityfairn -     看到这个新闻,我是真正的惊了!起因是中午午休快要 1.30 了,然后就被通报批评了。CEO 不仅禁止员工以后午休,还让各部门负责人写了检讨书。真实的“周扒皮”? 不多说,看

  • 21

  • 38

  • 10
    • qixinbo.info 3 years ago
    • Cache

    (转载)Harris角点检测原理

    (转载)Harris角点检测原理 原文在这里,中间增加了一些额外的...

  • 8
    • jiajunhuang.com 3 years ago
    • Cache

    [声明]本站所有文章禁止转载

    [声明]本站所有文章禁止转载 最近发现有好些个垃圾站直接全文抄袭本站的文章,请注意,本站此前的协议是“转载需注明作者及原链”,垃圾站直接抄文章不注明原链 是违反此协议的,自2020年1月10日12:00起,本站所有文章(包括以前的)都 禁止转载

  • 3

    乡建,其愿之宏美,其路之泥泞 作者:左希 发布时间: 2022-11-17 11:42

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK