PHP扩展开发--入门

环境介绍:

        centos7、php7.4

实现功能:写个简单类,包含name属性和一个say方法;

1、打开PHP安装的源码包,进入/usr/local/resource/php-7.4.24/ext

        执行命令:php ext_skel.php --ext hello

        结果如下:

        

 此时在./ext目录下会多出个hello目录,进入其中

2、 打开配置文件config.m4

        这个文件很重要,PHP系统如何构建扩展就根据它来的,配合phpize工具生成configure文件

        dnl相当于注释吧,本次扩展不依赖其他库,所以打开PHP_ARG_ENABLE就行(代码里说明

        如果所编写的扩展如果依赖其它的扩展或者lib库,就开启with)

        

        第一个参数是扩展名,第二个参数用于configure 脚本执行时输出的,AS_HELP_STRING用

        于--help时显示信息

        最底下,PHP_NEW_EXTENSION(hello, hello.c, $ext_shared)

        第二个参数为源文件,多个源文件用空格隔开,shared参数设置为$ext_shared吧

        (应该是:)),交给configure处理。。。

        其他一些M4宏方法,有兴趣的可以去细细查下,不多解释,7.4版本下,以上都是默认开启的

3、打开源文件hello.c

      内置了test1和test2方法,咱不管它

       (1)先摁个指针:zend_class_entry *hello_ce; 

       (2)在hello_module_entry结构体内,修改第4个参数为 PHP_MINIT(hello);

       (3)模块初始化:

                /* {{{ PHP_MINIT_FUNCTION
                 *  *  */
                PHP_MINIT_FUNCTION(hello)
                {
                        zend_class_entry ce;

                        //hello为类名(切记要有双引号),hello_methods是类的行为集合
                        INIT_CLASS_ENTRY(ce, "hello", hello_methods);

                        //zend_register_internal_class返回一个指针
                        hello_ce = zend_register_internal_class(&ce);

                        //定义name属性
                        zend_declare_property_null(hello_ce, "name", sizeof("name") - 1, ZEND_ACC_PUBLIC);
                        return SUCCESS;
                }
                /* }}} */

        (4)行为集合,方法结构体:

                //say为行为名称,arginfo_hello_say为参数验证

                const zend_function_entry hello_methods[] = {
                        PHP_ME(hello, say, arginfo_hello_say, ZEND_ACC_PUBLIC)
                        {NULL, NULL, NULL}
                };

        (5)参数验证,定义arginfo结构体:

·                ZEND_BEGIN_ARG_INFO_EX(arginfo_hello_say, 0, 0, 1)
                        ZEND_ARG_INFO(0, name)
                        ZEND_ARG_INFO(0, other)
                ZEND_END_ARG_INFO()

                生成zend_arg_info结构的数组比较繁琐,内核已经提供了相应的宏来处理此问题。

                头部:ZEND_BEGIN_ARG_INFO(name, pass_rest_by_reference)

                           ZEND_BEGIN_ARG_INFO_EX(name, pass_rest_by_reference, return_reference, required_num_args)

                           前两个参数统一:name结构体名称;pass_rest_by_reference(1|0)为1时表示所有参数都要以引入的形式传递 ;return_reference(1|0)1时返回值需要以引入的形式

                           返回;required_num_args必传参数的个数

                数据:ZEND_ARG_INFO(0, name)

                           第一个参数(1|0)为1表示必须以引入的方式传递参数,此处单独配置会覆盖头部pass_rest_by_reference;第二个为参数名称

                尾部:ZEND_END_ARG_INFO()

        (6)行为方法体具体实现:        

                /* {{{ string test_from( [long left ] [, long other] )
                 *  */
                PHP_FUNCTION(hello, say)
                {
                        zend_string *name, *other, *var;

                        ZEND_PARSE_PARAMETERS_START(1, 2)
                                Z_PARAM_STR(name)
                                Z_PARAM_OPTIONAL
                                Z_PARAM_STR(other)
                        ZEND_PARSE_PARAMETERS_END();

                        var = strpprintf(0, "hello %s", ZSTR_VAL(name));
                        if(ZSTR_LEN(other) != 0){
                                var = strpprintf(0, "hello %s from %s", ZSTR_VAL(name), ZSTR_VAL(other));
                        }

                        RETURN_STR(var);
                }
                /*}}}*/

               ps:在PHP7之前一直使用zend_parse_parameters函数获取参数。这个函数的作用,就是把传入的参数转换为PHP内核中相应的类型,方便在PHP扩展中使用。比如官网例子:

                if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "al|zb", &input, &offset, &z_length, &preserve_keys) == FAILURE) {

                            return;

                }

                ZEND_NUM_ARGS() TSRMLS_CC:规定传入参数的个数

                al|zb: 格式化字符串,指定传入参数与PHP内核类型的转换关系 a:zval, l:long,| 表示后面的参数可选 ,z: 表示参数是多种类型,要把传入的参数转换为zval类型,b:布尔

                FAST ZPP

                在PHP7中新提供的方式。是为了提高参数解析的性能。对应经常使用的方法,建议使用FAST ZPP方式。

                以ZEND_PARSE_PARAMETERS_START(1, 2)开头。

                第一个参数表示必传的参数个数,第二个参数表示最多传入的参数个数。

                以ZEND_PARSE_PARAMETERS_END();结束。

                中间是传入参数的解析。

                值得注意的是,一般FAST ZPP的宏方法与zend_parse_parameters的specifier是一一对应的。如:

                Z_PARAM_ARRAY 对应 a

                Z_PARAM_LONG 对应 l

                Z_PARAM_OPTIONAL 对应 |

                FAST ZPP相应的宏方法可以查看官方网站 https://wiki.php.net/rfc/fast_zpp#proposal

        (7)完整代码(注意顺序):

                zend_class_entry *hello_ce;

                PHP_METHOD(hello, say)
                {       
                        zend_string *name, *other, *var;        
                        ZEND_PARSE_PARAMETERS_START(1, 2)
                        Z_PARAM_STR(name)
                        Z_PARAM_OPTIONAL
                        Z_PARAM_STR(other)
                        ZEND_PARSE_PARAMETERS_END();

                        var = strpprintf(0, "hello %s", ZSTR_VAL(name));
                        if(ZSTR_LEN(other) != 0){
                                var = strpprintf(0, "hello %s from %s", ZSTR_VAL(name), ZSTR_VAL(other));

                        }

                        RETURN_STR(var);
                }

                ZEND_BEGIN_ARG_INFO_EX(arginfo_hello_say, 0, 0, 1)
                        ZEND_ARG_INFO(0, name)
                        ZEND_ARG_INFO(0, other)
                ZEND_END_ARG_INFO()
                const zend_function_entry hello_methods[] = {
                        PHP_ME(hello, say, arginfo_hello_say, ZEND_ACC_PUBLIC)
                        {NULL, NULL, NULL}
                };


                PHP_MINIT_FUNCTION(hello)
                {
                        zend_class_entry ce;
                       INIT_CLASS_ENTRY(ce, "hello", hello_methods);
                        hello_ce = zend_register_internal_class(&ce);
                        zend_declare_property_null(hello_ce, "name", sizeof("name") - 1, ZEND_ACC_PUBLIC);
                        return SUCCESS;
                }

4、编译,安装 ,/usr/local/resource/php-7.4.24/ext/hello目录下

        /opt/php/bin/phpize(根据安装的PHP位置)

        ./configure --enable-hello --with-php-config=/opt/php/bin/php-config

        make && make install

        打开php.ini,添加extension=hello.so

        php -m查看是否加载hello扩展

5、测试

       

        

                 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值