php扩展开发入门
来源:互联网 发布:java飞机大战扇形子弹 编辑:程序博客网 时间:2024/05/22 05:18
我们要开发的扩展的php原型是:
<?php// 调用一个可变参函数,输出函数名和参数,返回调用后的结果function calltask(callable $func[, mixed $arg1[, ...]]);// 原型可变参写法function calltask(... $args) { $func = array_shift($args); if (!is_callable($func)) { printf("the function is not callable:%s\n", $func); return false; } // 输出 printf("you call func:%s\n", $func); foreach ($args as $i=>$arg) { printf("arg[%d] type=%d len=%d val=%s \n", $i, typeof($arg), strlen($arg), strval($arg)); } return $func(... $args);}
我的开发环境是:
系统: CentOS 7
PHP: 7.0+
gcc :4.8.4
PHP已经提供了工具用来创建扩展,并初始化代码:ext_skel
$ cd php-src/ext$ ./ext_skel --extname=hello
工具会在当前目录生成 hello 文件夹。
修改配置文件
cd到hello,工具已经初始化了目录,打开配置文件 config.m4:
dnl If your extension references something external, use with:dnl PHP_ARG_WITH(hello, for hello support,dnl Make sure that the comment is aligned:dnl [ --with-hello Include hello support])dnl Otherwise use enable:dnl PHP_ARG_ENABLE(hello, whether to enable hello support,dnl Make sure that the comment is aligned:dnl [ --enable-hello Enable hello support])
dnl 是注释符,表示当前行是注释。这段话是说如果此扩展依赖其他扩展,去掉PHP_ARG_WITH段的注释符;否则去掉PHP_ARG_ENABLE段的注释符。显然我们不依赖其他扩展或lib库,所以去掉PHP_ARG_ENABLE段的注释符:
PHP_ARG_ENABLE(hello, whether to enable hello support,Make sure that the comment is aligned:[ --enable-hello Enable hello support])
书写代码
工具生成的hello.c,写上我们的实现:
/* proto function calltask(callable $func[, mixed $arg1[, ...]]);*/PHP_FUNCTION(calltask){ int i, status, argc = ZEND_NUM_ARGS(); zval *args = NULL; zval retval; // use FAST_ZPP get any count of args, args use original args pointer, no need to free here#ifndef FAST_ZPP if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) { RETURN_FALSE; } #else ZEND_PARSE_PARAMETERS_START(1, -1) Z_PARAM_VARIADIC('+', args, argc) ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);#endif if (argc < 1) { WRONG_PARAM_COUNT; } // 第一个参数为函数名 取出来 zval *thefunc = &(args[0]); php_printf("you will call: %s argc=%d is_callable=%d\n", Z_STRVAL(*thefunc), argc, zend_is_callable(thefunc, IS_CALLABLE_CHECK_NO_ACCESS, NULL)); if (!zend_is_callable(thefunc, IS_CALLABLE_CHECK_NO_ACCESS, NULL)) { php_printf("the function is not callable:%s\n", Z_STRVAL(*thefunc)); RETURN_FALSE; } // 从第二个参数开始,把参数打印出来 for (i=1; i<argc; i++) { convert_to_string_ex(&args[i]); php_printf("arg[%d] type=%d len=%d val=%s \n", i, Z_TYPE(args[i]), Z_STRLEN(args[i]), Z_STRVAL(args[i])); } // 使用zend_API.h中的call_user_function_ex调用 status = call_user_function_ex(EG(function_table), NULL, thefunc, &retval, argc-1, (argc>1?args+1:NULL), 0, NULL); // 判断返回值 if (status == SUCCESS && !Z_ISUNDEF(retval)) { php_printf("the function success:%d\n", status); //zval_ptr_dtor(return_value); //ZVAL_COPY_VALUE(return_value, &retval); } else { php_printf("the function failed:%d\n", status); //zval_ptr_dtor(return_value); //ZVAL_NULL(return_value); } php_printf("the call over: %s argc=%d status=%d\n", Z_STRVAL(*thefunc), argc); //efree(args);// Z_PARAM_VARIADIC 的args指针来自于复制函数原参数指针,不需要free RETURN_ZVAL(&retval, 1, 1);//RETURN_TRUE;// 返回该返回值的类型}
添加到编译列表里:
const zend_function_entry hello_functions[] = { PHP_FE(hello, NULL) /*添加这行*/ PHP_FE(confirm_hello_compiled, NULL) /* For testing, remove later. */ PHP_FE_END /* Must be the last line in hello_functions[] */};
编译与安装
$ phpize$ ./configure --with-php-config=/usr/local/php7/bin/php-config$ make && make install
修改php.ini,开启扩展,若找不到可以用phpinfo()查看使用哪个配置文件.
make install会输出你的php扩展的路径:
Installing shared extensions: /usr/local/php/lib/php/extensions/no-debug-non-zts-20151012/
其实不用关心这个路径。相信来学习扩展开发的同学都知道哪里配置php.ini,如何重启对应的apache或者fpm,这里不多说。
extension=hello.so
写个脚本测试,此脚本在ext_skel会自动生成, hello.php:
<?php$br = (php_sapi_name() == "cli")? "":"<br>";if(!extension_loaded('hello')) { dl('./module/hello.' . PHP_SHLIB_SUFFIX);}$module = 'hello';/* 测试打印扩展中的函数列表$functions = get_extension_funcs($module);echo "Functions available in the test extension:$br\n";foreach($functions as $func) { echo $func."$br\n";}echo "$br\n";$function = 'confirm_' . $module . '_compiled';if (extension_loaded($module)) { $str = $function($module);} else { $str = "Module $module is not compiled into PHP";}echo "called in script: $str\n";*///$ret = calltask($function, 100, 2.2);$func2 = function(... $args) { $args[0] = "make a str:".$args[0]; return sprintf(... $args);};$func1 = 'printf';//$ret = calltask($func1, 'FORMAT_FROM_PARAM:%s:%d\n', date('Y-m-d H:i:s'), __LINE__);$ret = calltask($func2, 'FORMAT_FROM_PARAM:%s:%d\n', date('Y-m-d H:i:s'), __LINE__);echo "the ret in php=";var_dump($ret);
输出:
you will call: ??argc=4 is_callable=1arg[1] type=6 len=25 val=FORMAT_FROM_PARAM:%s:%d\n arg[2] type=6 len=19 val=2017-08-01 19:09:14 arg[3] type=6 len=2 val=28 the function success:0the call over: ??argc=4 status=8the ret in php=string(53) "make a str:FORMAT_FROM_PARAM:2017-08-01 19:09:14:28\n"
运行成功。
祝小伙伴们开发顺利。
阅读全文
0 0
- php扩展开发入门
- 【原创】PHP扩展开发入门
- PHP扩展开发(1):快速入门
- PHP扩展开发(1):快速入门
- PHP扩展编写入门
- php扩展练习-入门
- PHP扩展开发(1):快速入门(转载)
- linux下php扩展开发入门之hello word
- PHP扩展开发-创建扩展
- Firefox扩展开发入门
- Chrome扩展开发入门
- chrome扩展开发入门
- PHP7扩展开发入门
- Chrome扩展开发入门
- 开发PHP扩展模块
- 开发PHP扩展模块
- PHP扩展开发笔记
- 开发php扩展
- JS函数6
- Promise 是什么?
- jquery准确获取元素
- 16CF1--B-1002
- CodeChef
- php扩展开发入门
- Java中list集合为空或为null的区别
- Android 基于SurfaceView 开发示波器
- MemoryAnalyzer 调试内存泄漏
- 递归算法问题: 有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不会死。问: 第20个月的兔子总对数为多少?(提示:先分析兔子的增长规律)
- 爬虫遇到的问题
- 深入理解IIS的多线程工作机制
- OpenCV—形态学运算定义与实现
- 原生android工程实现RN集成