PHP7扩展开发之常量定义

简介: # 前言 这次,我们将演示如何在PHP扩展中定义一个常量。要实现的PHP代码如下: ``` php ``` 我们将演示在PHP扩展中定义三个常量。如上面代码中的三个define。 # 代码 ## 基础代码 这个扩展,我们将在say扩展的 ``PHP_MINIT_FUNCTION(say)`` 方法上增加相应的代码。say扩展相关代码大家请看这篇博文。[PHP7扩展开发之

前言

这次,我们将演示如何在PHP扩展中定义一个常量。要实现的PHP代码如下:

    <?php
        define("__ARR__", array('2', 'site'=>"www.bo56.com"));  
        define("__SITE__", "www.bo56.com", true);
        define("say\__SITE__", "bo56.com");
        var_dump(__ARR__);
        var_dump(__site__);
        var_dump(say\__SITE__);
    ?>
我们将演示在PHP扩展中定义三个常量。如上面代码中的三个define。

代码

基础代码

这个扩展,我们将在say扩展的 PHP_MINIT_FUNCTION(say) 方法上增加相应的代码。say扩展相关代码大家请看这篇博文。PHP7扩展开发之hello word 文中已经详细介绍了如何创建一个扩展和提供了源码下载。

增加的代码如下

//增加两个方法
//释放hash
static void say_hash_destroy(HashTable *ht)
    zend_string *key;
    zval *element;
    if (((ht)->u.flags & HASH_FLAG_INITIALIZED)) {
        ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, element) {
            if (key) {
                free(key);
            }
            switch (Z_TYPE_P(element)) {
                case IS_STRING:
                    free(Z_PTR_P(element));
                    break;
                case IS_ARRAY:
                    say_hash_destroy(Z_ARRVAL_P(element));
                    break;
            }
        } ZEND_HASH_FOREACH_END();
        free(HT_GET_DATA_ADDR(ht));
    }   
    free(ht);
}
//释放数组和字符串
static void say_entry_dtor_persistent(zval *zvalue)
    if (Z_TYPE_P(zvalue) == IS_ARRAY) {
        say_hash_destroy(Z_ARRVAL_P(zvalue));
    } else if (Z_TYPE_P(zvalue) == IS_STRING) {
        zend_string_release(Z_STR_P(zvalue));
    }
}
//PHP_MINIT_FUNCTION(say)方法的PHP扩展源码: 扩展初始化的调用此方法
PHP_MINIT_FUNCTION(say)
{
    zend_constant c;
    zend_string *key;
    zval value;
    ZVAL_NEW_PERSISTENT_ARR(&c.value);
    zend_hash_init(Z_ARRVAL(c.value), 0, NULL,
                        (dtor_func_t)say_entry_dtor_persistent, 1);
    add_index_long(&c.value, 0, 2);
    key = zend_string_init("site", 4, 1);
    ZVAL_STR(&value, zend_string_init("www.bo56.com", 12, 1));
    zend_hash_update(Z_ARRVAL(c.value), key, &value);
    c.flags = CONST_CS|CONST_PERSISTENT;
    c.name = zend_string_init("__ARR__", 7, 1);
    c.module_number = module_number;
    zend_register_constant(&c);

    REGISTER_STRINGL_CONSTANT("__SITE__", "www.bo56.com", 12, CONST_PERSISTENT);
    REGISTER_NS_STRINGL_CONSTANT("say", "__SITE__", "bo56.com", 8, CONST_CS|CONST_PERSISTENT);

}
//扩展卸载的时候调用此方法
PHP_MSHUTDOWN_FUNCTION(say)
{
    zval *val;
    val = zend_get_constant_str("__ARR__", 7);
    say_hash_destroy(Z_ARRVAL_P(val));
    ZVAL_NULL(val);
    return SUCCESS;
}

代码说明

一般情况下,在扩展中只建议定义null,bool,long,double,string几种类型的常量。因为内核只提供了这几种类型的宏方法。
常量定义的宏方法在Zend/zend_constants.h文件中。想定义一个常量,很简单,只要调用对应的宏方法即可。如:

REGISTER_STRINGL_CONSTANT("__SITE__", "www.bo56.com", 12, CONST_PERSISTENT);

宏方法的最后一个参数是一些标识符。
CONST_PERSISTENT 表示为持久的。常驻内存。
CONST_CS 表示为区分大小写。
注意我们上面定义常量时使用的是__SITE__,但是调用的时候使用的是__site__。

还有一套可以指定命名空间的宏方法。宏方法中带NS。如:

REGISTER_NS_STRINGL_CONSTANT("say", "__SITE__", "bo56.com", 8, CONST_CS|CONST_PERSISTENT);

第一个参数就是命名空间。

为了展示常量定义的一些细节。我们定义了一个__ARR__常量。
ZVAL_NEW_PERSISTENT_ARR(&c.value);我们想让__ARR__为持久的。所以使用ZVAL_NEW_PERSISTENT_ARR创建一个数组。
数组创建完后,我们需要初始化。初始化的代码就是

zend_hash_init(Z_ARRVAL(c.value), 0, NULL,
                        (dtor_func_t)say_entry_dtor_persistent, 1);

参数中的say_entry_dtor_persistent是一个析构函数,用于释放数组的元素。

到这里,如果编译运行。当程序执行结束的时候,你会发现一个致命错误。错误信息如下:

Fatal error: Internal zval's can't be arrays, objects or resources in Unknown on line 0

因为在程序执行完毕,内部zval释放的时候,会进行类型检测。如果发现是array object或者resources,则会报错。可以查看Zend/zend_variables.c文件中_zval_internal_dtor方法。
为了解决这个问题,我们需要手动释放我们创建的__ARR__相关的数组。
模块卸载时执行的方法,是优先Zend内部zval释放方法之前调用的。因此,我们只要在PHP_MSHUTDOWN_FUNCTION(say)方法中手动释放。不再让Zend去释放就可以解决了。

更多函数说明请查看

目录
相关文章
|
1月前
|
数据采集 存储 缓存
PHP爬虫的使用与开发
本文深入探讨了PHP爬虫的使用与开发,涵盖基本原理、关键技术、开发实践及优化策略。从发送HTTP请求、解析HTML到数据存储,再到处理反爬机制,全面指导读者构建高效可靠的爬虫程序。
57 3
ly~
|
4月前
|
存储 供应链 小程序
除了微信小程序,PHP 还可以用于开发哪些类型的小程序?
除了微信小程序,PHP 还可用于开发多种类型的小程序,包括支付宝小程序、百度智能小程序、抖音小程序、企业内部小程序及行业特定小程序。在电商、生活服务、资讯、工具、娱乐、营销等领域,PHP 能有效管理商品信息、订单处理、支付接口、内容抓取、复杂计算、游戏数据、活动规则等多种业务。同时,在企业内部,PHP 可提升工作效率,实现审批流程、文件共享、生产计划等功能;在医疗和教育等行业,PHP 能管理患者信息、在线问诊、课程资源、成绩查询等重要数据。
ly~
96 6
|
4月前
|
设计模式 算法 数据库连接
PHP中的设计模式:提高代码的可维护性与扩展性本文旨在探讨PHP中常见的设计模式及其应用,帮助开发者编写出更加灵活、可维护和易于扩展的代码。通过深入浅出的解释和实例演示,我们将了解如何使用设计模式解决实际开发中的问题,并提升代码质量。
在软件开发过程中,设计模式是一套经过验证的解决方案模板,用于处理常见的软件设计问题。PHP作为流行的服务器端脚本语言,也有其特定的设计模式应用。本文将重点介绍几种PHP中常用的设计模式,包括单例模式、工厂模式和策略模式,并通过实际代码示例展示它们的具体用法。同时,我们还将讨论如何在实际项目中合理选择和应用这些设计模式,以提升代码的可维护性和扩展性。
87 4
|
13天前
|
开发框架 小程序 前端开发
圈子社交app前端+后端源码,uniapp社交兴趣圈子开发,框架php圈子小程序安装搭建
本文介绍了圈子社交APP的源码获取、分析与定制,PHP实现的圈子框架设计及代码编写,以及圈子小程序的安装搭建。涵盖环境配置、数据库设计、前后端开发与接口对接等内容,确保平台的安全性、性能和功能完整性。通过详细指导,帮助开发者快速搭建稳定可靠的圈子社交平台。
119 18
|
2月前
|
XML JSON API
【PHP开发专栏】PHP RESTful API设计与开发
随着互联网技术的发展,前后端分离成为Web开发的主流模式。本文介绍RESTful API的基本概念、设计原则及在PHP中的实现方法。RESTful API是一种轻量级、无状态的接口设计风格,通过HTTP方法(GET、POST、PUT、DELETE)操作资源,使用JSON或XML格式传输数据。在PHP中,通过定义路由、创建控制器、处理HTTP请求和响应等步骤实现RESTful API,并强调了安全性的重要性。
43 2
|
2月前
|
XML 安全 PHP
PHP与SOAP Web服务开发:基础与进阶教程
本文介绍了PHP与SOAP Web服务的基础和进阶知识,涵盖SOAP的基本概念、PHP中的SoapServer和SoapClient类的使用方法,以及服务端和客户端的开发示例。此外,还探讨了安全性、性能优化等高级主题,帮助开发者掌握更高效的Web服务开发技巧。
|
3月前
|
NoSQL 安全 Linux
MongoDB PHP 扩展
10月更文挑战第19天
18 0
MongoDB PHP 扩展
|
3月前
|
SQL 关系型数据库 MySQL
PHP与MySQL协同工作的艺术:开发高效动态网站
在这个后端技术迅速迭代的时代,PHP和MySQL的组合仍然是创建动态网站和应用的主流选择之一。本文将带领读者深入理解PHP后端逻辑与MySQL数据库之间的协同工作方式,包括数据的检索、插入、更新和删除操作。文章将通过一系列实用的示例和最佳实践,揭示如何充分利用这两种技术的优势,构建高效、安全且易于维护的动态网站。
|
3月前
|
Java PHP
PHP作为广受青睐的服务器端脚本语言,在Web开发中占据重要地位。理解其垃圾回收机制有助于开发高效稳定的PHP应用。
【10月更文挑战第1天】PHP作为广受青睐的服务器端脚本语言,在Web开发中占据重要地位。其垃圾回收机制包括引用计数与循环垃圾回收,对提升应用性能和稳定性至关重要。本文通过具体案例分析,详细探讨PHP垃圾回收机制的工作原理,特别是如何解决循环引用问题。在PHP 8中,垃圾回收机制得到进一步优化,提高了效率和准确性。理解这些机制有助于开发高效稳定的PHP应用。
58 3
|
6月前
|
安全 IDE 编译器
深入理解PHP 7的新特性及其对现代Web开发的影响
【7月更文挑战第30天】本文将深入探索PHP 7版本中引入的关键新特性,并分析这些改进如何优化现代Web开发实践。通过对比PHP 5和PHP 7的性能差异,我们将揭示PHP 7如何提升应用响应速度和资源利用效率。此外,本文还将讨论PHP 7对开发者工作流程的影响,包括新的语言特性、错误处理机制以及内置函数的增强,旨在为读者提供全面了解PHP 7所带来的变革性影响。