目录
1、什么是PHP扩展
2、开发环境
3、开始开发自己的扩展
3.1 创建一个名为hello的扩展
3.2 config.m4配置文件
3.3 编写代码
4、测试
php本身带有86个扩展,扩展是对php语言功能的一个延伸,php的核心由两部分组成:最底层的 Zend引擎
和 PHP内核
。ze把脚本解析成机器可读的符号,也会处理内存管理,变量作用域,程序调度。PHP内核则主要涉及主机环境(Apache,IIS,Nginx),处理与主机的通信。
当php提供的功能不能满足需求的时候,就有两种办法实现自己的需求,一是通过PHP函数来解决问题,另一种就是通过扩展来解决。扩展采用C语言开发还能一定程度上解决性能问题。所以对比于函数机制,PHP扩展有以下优点:
1、如果应用注重效率,使用非常复杂的算法,推荐使用PHP扩展。
2、有些系统调用PHP不能直接访问(如Linux的fork()函数创建进程),需要编写成PHP扩展。
3、应用不想暴露关键代码,可以创建扩展使用。
4、同时因为PHP解析器源码为C编写,所以扩展也可以调用许多PHP解析器的函数。
Linux、PHP-7.3.4、GCC
cd PHP源码目录
./configure --prefix=[自己要安装的目录] --enable-debug
make && make install
到PHP源码的ext目录下会有一个ext_skel.php文件,创建一个叫hello的扩展,有的版本的PHP是./ext_skel --extname=hello
php ext_skel.php --ext hello
开发PHP扩展,在写C代码之前,要先配置一下这里。我们打开可以看到详细的注释说明,dnl是注释语法。
如果你的扩展用到了外部依赖,就配置--with-hello选项,否则配置--enable-hello选项
cd hello
vim config.m4
#删除这下面3行的del注释
PHP_ARG_ENABLE(hello, whether to enable hello support,
Make sure that the comment is aligned:
[ --enable-hello Enable hello support])
PHP_ARG_WITH和PHP_ARG_ENABLE这两个宏用来配置configure选项,一个配置需要外部依赖,另一个配置不需要外部依赖;
配置好的内容,在后面执行configure --help时可以看到。
php_hello.h头文件
类似于C语音的头文件,包含了一些自定义的结构和函数声明,本例中不需要改动。
hello.c代码文件
真正的逻辑代码都在这个文件中。
打开hello.c文件。
整个扩展的入口是zend_module_entry这个结构,具体的定义可以在Zend目录下的zend_modules.h文件中看到,一共有十几个属性,快速跳过,我们暂时只需要"hello"。
zend_module_entry hello_module_entry = {
STANDARD_MODULE_HEADER,
"hello", /* Extension name */
hello_functions, /* zend_function_entry */
NULL, /* PHP_MINIT - Module initialization */
NULL, /* PHP_MSHUTDOWN - Module shutdown */
PHP_RINIT(hello), /* PHP_RINIT - Request initialization */
NULL, /* PHP_RSHUTDOWN - Request shutdown */
PHP_MINFO(hello), /* PHP_MINFO - Module info */
PHP_HELLO_VERSION, /* Version */
STANDARD_MODULE_PROPERTIES
};
暂时都不需要修改,知道这是一个入口就行。顺着这个入口,我们继续看怎么给扩展添加方法,在hello_functions[]方法数组中已经有了一个示例方法confirm_hello_compiled,我们参考它写我们的方法hello_world。
编译列表
static const zend_function_entry hello_functions[] = {
PHP_FE(hello_test1, arginfo_hello_test1)
PHP_FE(hello_test2, arginfo_hello_test2)
PHP_FE(hello_world, NULL) //我们自定义的方法
PHP_FE_END
};
功能实现
PHP_FUNCTION(hello_world)
{
php_printf("Hello World!\n");
RETURN_TRUE;
}
编译与安装
$ /PHP安装目录/bin/phpize
#第一个参数是依赖部件,不加如果调用了PHP内部函数将编译不了,第二个是设置DEBUG
$ ./configure --with-php-config=/PHP安装目录/bin/php-config --enable-debug
$ make & make install
之后会显示这个.so文件在哪里,这时我们只需要在php.ini中添加上扩展的配置
extension = hello.so
写一个test.php方法,执行脚本就可以看到"Hello World!"
实际上自动生成的hello.c里面已经有两个例子了hello_test1教你如何直接输出,原理同hello_world;
PHP_FUNCTION(hello_test1)
{
ZEND_PARSE_PARAMETERS_NONE();
php_printf("The extension %s is loaded and working!\r\n", "hello");
}
PHP_FUNCTION(hello_test2)
{
char *var = "World";
size_t var_len = sizeof("World") - 1;
zend_string *retval;
//参数解析
ZEND_PARSE_PARAMETERS_START(0, 1)
Z_PARAM_OPTIONAL
Z_PARAM_STRING(var, var_len)
ZEND_PARSE_PARAMETERS_END();
retval = strpprintf(0, "Hello %s", var);
RETURN_STR(retval);
}
hello_test2将你如何输入参数,参数解析方法已经定义好了,运行测试看看结果