PHP扩展开发与内核应用阅读笔记---php的作用域以及如何在扩展中定义,查找php变量

本文介绍了PHP中函数内外变量无法互用的原因,这源于PHP使用符号表管理变量,每个作用域拥有独立的符号表。在函数内部,全局变量并不在当前激活的符号表中。通过阅读 Zend/zend_globals.h 文件,可以了解如何在PHP扩展中查找和定义变量。文中提供了在扩展中创建PHP变量的步骤,包括创建zval结构、设置变量值以及将其加入当前作用域的符号表。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先提供书的地址:php扩展开发与内科应用,并向作者表示感谢!同时欢迎同看此书的人加入QQ群:76761320

1:无法在函数中使用在函数外定义的变量的原因

由于php中定义的变量是存储在一个用HashTable实现的符号表里。当用户在PHP中调用一个函数或者类的方法时,内核会创建一个新的符号表并激活,这也就是为什么我们无法在函数中使用在函数外定义的变量的原因(因为它们分属两个符号表,一个当前作用域的,一个全局作用域的)。如果不是在一个函数里,则全局作用域的符号表处于激活状态。

然而我们是通过什么来找到当前作用域的符号表和全局作用域的符号表的呢?

我们现在打开php源码下的Zend/zend_globals.h文件,看一下_zend_execution_globals结构体,会在其中发现这么两个element:

struct _zend_executor_globals {
    ...
    HashTable symbol_table;
    HashTable *active_symbol_table;
    ...
};
其中的 symbol_table元素可以通过EG宏来访问,它代表着PHP的全局变量,如$GLOBALS,其实从根本上来讲,$GLOBALS不过是EG(symbol_table)的一层封装而已。 与之对应,下面的active_symbol_table元素也可以通过EG(active_symbol_table)的方法来访问,它代表的是处于当前作用域的变量符号表。

2:在扩展中创建一个php变量

我们可以先构思一下步骤:

  • 创建一个zval结构,并设置其类型。
  • 设置值为'bar'。
  • 将其加入当前作用域的符号表,只有这样用户才能在PHP里使用这个变量。
  • 具体的代码为
    zval *fooval;
 
    MAKE_STD_ZVAL(fooval);
    ZVAL_STRING(fooval, "bar", 1);
    ZEND_SET_SYMBOL( EG(active_symbol_table) ,  "foo" , fooval);

首先,我们声明一个zval指针fooval,并使用MAKE_STD_ZVAL宏来申请一块内存。然后通过ZVAL_STRING宏将值设置为‘bar’,最后使用ZEND_SET_SYMBOL将这个zval加入到当前的符号表里去,并将其label定义成foo,这样用户就可以在代码里通过$foo来使用它了。
3:在扩展中调用一个已经定义的php变量
内核提供了操作HashTable的API:zend_hash_find() 通过这个函数可以找到当前某个作用域下用户已经定义好的变量。
  • 定义了一个指向指针的指针
  • 通过zend_hash_find去EG(active_symbol_table)作用域下寻找名称为foo($foo)的变量,如果成功找到,此函数将返回SUCCESS。并把它的地址赋给我们在调用zend_hash_find()函数传递的fooval参数,也就是说此时fooval就指向了我们要找的数据。如果没有找到,那它不会对我们fooval参数做任何修改,并返回FAILURE常量。
  • if判断输出结果
  • 具体代码为:
    zval **fooval;
 
    if (zend_hash_find(
            EG(active_symbol_table), //这个参数是地址,如果我们操作全局作用域,则需要&EG(symbol_table)
            "foo",
            sizeof("foo"),
            (void**)&fooval
        ) == SUCCESS
    )
    {
        php_printf("成功发现$foo!");
    }
    else
    {
        php_printf("当前作用域下无法发现$foo.");
    }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值