php扩展开发(一)自己写一个类

本文介绍了如何使用C语言为PHP开发扩展,从搭建开发环境、配置编译选项到实现自定义函数与类的过程。详细讲解了如何声明函数、类及其实现方法。

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

php扩展开发(一)自己写一个类

平时自己用php写一个类包是非常容易的,直接 $zhangleiinstance = new Abelappplication();

但是我们如何用c语言在php中写一个函数和类呢

1.下载php源码包,然后在php的源码包目录的ext下面创建框架骨架

./ext_skel --extname=helloworld

2.修改config.m4

##动态编译选项,通过.so的方式链接,去掉dnl注释:

PHP_ARG_WITH(helloworld, for helloworld support,
Make sure that the comment is aligned:
[  --with-helloworld             Include helloworld support])

##静态编译选项,通过enable来启用,去掉dnl注释:

 PHP_ARG_ENABLE(helloworld, whether to enable helloworld support,
 Make sure that the comment is aligned:
 [  --enable-helloworld           Enable helloworld support])

3.phpize生成解析文件(我是yum装的所以不需要指定路径)

phpize 
./configure && make &&make install

4.在头文件中声明自己的函数和自己的类

声明函数用PHP_FUNCTION宏

声明类包用PHP_METHOD宏、

我在phpabelapplication.h中声明自己的函数和类以及方法

PHP_FUNCTION(helloworld);
PHP_METHOD(Abel_application,__construct);
PHP_METHOD(Abel_application,__destruct);
PHP_METHOD(Abel_application,ourMethod1);
PHP_METHOD(Abel_application,ourMrthod2);

5.声明要接收的参数

ZEND_BEGIN_ARG_INFO_EX(arg_abel_info,0,0,2)
    ZEND_ARG_INFO(0,name)
ZEND_END_ARG_INFO()

解释:

ZEND_ARG_INFO     声明普通参数
ZEND_ARG_OBJ_INFO     声明对象类型的参数
ZEND_ARG_ARRAY_INFO     声明数组类型的参数
ZEND_ARG_PASS_INFO(pass_by_ref)     pass_by_ref为1时,强制设置后续的参数为引用类型

6.在栈上声明一个函数列表的数组(这一步用于注册)

const zend_function_entry abel_function[] = {
    PHP_FE(helloworld,NULL)
    PHP_ME(Abel_application,__construct,NULL,ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
    PHP_ME(Abel_application,__destruct,NULL,ZEND_ACC_PUBLIC|ZEND_ACC_DTOR)
    PHP_ME(Abel_application,ourMethod1,arg_abel_info,ZEND_ACC_PUBLIC)
    PHP_ME(Abel_application,ourMethod2,arg_abel_info,ZEND_ACC_PUBLIC)
    PHP_FE_END
};

7.实现方法体

PHP_FUNCTION(helloworld)
{
        php_printf("Hello Ligang,this is the first extension!\n");
        RETURN_TRUE;
}

PHP_METHOD(Abel_application,__construct)
{
    php_printf("hello,zhang lei this is your first construct extension");
};

PHP_METHOD(Abel_application,__destruct)
{
    php_printf("hello,zhang lei this is your first destrcut extension");
};

PHP_METHOD(Abel_application,ourMethod1)
{

};

PHP_METHOD(Abel_application,ourMethod2)
{

};

8.注册到SAPI初始化中

PHP_MINIT_FUNCTION(abel_application)
{
        /* If you have INI entries, uncomment these lines
        REGISTER_INI_ENTRIES();
        */

        zend_class_entry abel_entry;
        INIT_CLASS_ENTRY(abel_entry,"abel_application",abel_function);
        abel_ce = zend_register_internal_class_ex(&abel_entry,NULL);
        zend_declare_property_null(abel_ce,ZEND_STRL("name"),ZEND_ACC_PUBLIC TSRMLS_CC);
        return SUCCESS;
}

注意:

zend_module_entry abel_application_module_entry = {
    STANDARD_MODULE_HEADER,
    "abel_application",
    abel_function,
    PHP_MINIT(abel_application),
    PHP_MSHUTDOWN(abel_application),
    PHP_RINIT(abel_application),
    PHP_RSHUTDOWN(abel_application),
    PHP_MINFO(abel_application),
    PHP_ABEL_APPLICATION_VERSION,
    STANDARD_MODULE_PROPERTIES
};

要把module条目中的abel_function 的参数改为刚才声明的函数列表数组

tipi中是这样说的

这样的结构在PHP的源码中有多处使用, 比如在PHP扩展开发中,每个扩展都需要定义一个zendmoduleentry结构体。 这个结构体的作用与sapimodulestruct结构体类似,都是一个类似模板方法模式的应用。 在PHP的生命周期中如果需要调用某个扩展,其调用的方法都是zendmoduleentry结构体中指定的方法, 如在上一小节中提到的在执行各个扩展的请求初始化时,都是统一调用requeststartupfunc方法, 而在每个扩展的定义时,都通过宏PHPRINIT指定requeststartupfunc对应的函数。 以VLD扩展为例:其请求初始化为PHPRINIT(vld),与之对应在扩展中需要有这个函数的实现: PHPRINITFUNCTION(vld) { }

9.调用实例:

<?php
$a = new Abel_application();
$a->name=3;
$aa = $a->ourMethod1(1,2,3,4,5,6,7,8,9);
echo "\r\n";
var_dump($aa);
echo "\r\n";
//helloworld();
//var_dump($a);

再次回顾tipi中的声明周期

开始和结束

PHP开始执行以后会经过两个主要的阶段:处理请求之前的开始阶段和请求之后的结束阶段。 开始阶段有两个过程:第一个过程是模块初始化阶段(MINIT), 在整个SAPI生命周期内(例如Apache启动以后的整个生命周期内或者命令行程序整个执行过程中), 该过程只进行一次。第二个过程是模块激活阶段(RINIT),该过程发生在请求阶段, 例如通过url请求某个页面,则在每次请求之前都会进行模块激活(RINIT请求开始)。 例如PHP注册了一些扩展模块,则在MINIT阶段会回调所有模块的MINIT函数。 模块在这个阶段可以进行一些初始化工作,例如注册常量,定义模块使用的类等等。 模块在实现时可以通过如下宏来实现这些回调函数:

PHPMINITFUNCTION(myphpextension) { // 注册常量或者类等初始化操作 return SUCCESS; } 请求到达之后PHP初始化执行脚本的基本环境,例如创建一个执行环境,包括保存PHP运行过程中变量名称和值内容的符号表, 以及当前所有的函数以及类等信息的符号表。然后PHP会调用所有模块的RINIT函数, 在这个阶段各个模块也可以执行一些相关的操作,模块的RINIT函数和MINIT回调函数类似:

PHPRINITFUNCTION(myphpextension) { // 例如记录请求开始时间 // 随后在请求结束的时候记录结束时间。这样我们就能够记录下处理请求所花费的时间了 return SUCCESS; } 请求处理完后就进入了结束阶段,一般脚本执行到末尾或者通过调用exit()或die()函数, PHP都将进入结束阶段。和开始阶段对应,结束阶段也分为两个环节,一个在请求结束后停用模块(RSHUTDOWN,对应RINIT), 一个在SAPI生命周期结束(Web服务器退出或者命令行脚本执行完毕退出)时关闭模块(MSHUTDOWN,对应MINIT)。

PHPRSHUTDOWNFUNCTION(myphpextension) { // 例如记录请求结束时间,并把相应的信息写入到日至文件中。 return SUCCESS; }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值