本文主要向您介绍PHP语言扩展的实现,并通过具体的例子向您展示。 希望对您学习php语言有所帮助。
PHP的扩展实现后有两种形式,一种是扩展一个新的方法,一种是扩展一个类。
php版本是php7
1. 扩展方法
准备代码目录
mkdir zcjcdzcj
新建三个文件,通过这三个文件生成扩展名(也有工具可以手动生成,具体参见参考文章)
//php_extension,extension.c**规范要注意**
配置.m4、php_zcj.h、zcj.c
一份是phpize打算编译扩展的配置文件,一份是包含的头文件,一份是源代码文件。
config.m4是phpize的参数文件,--enable可以改为--witth,--enable是动态编译,--with是静态编译,不知道两者有什么区别,c/c++高手还是需要它让大家知道。
PHP_ARG_ENABLE(zcj, whether to enable zcj support,Make sure that the comment is aligned: [ --enable-zcj Enable zcj support])if test "$PHP_ZCJ" != "no"; then PHP_NEW_EXTENSION(zcj, zcj.c, $ext_shared,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1) fi
我这里的扩展名是zcj,如果你的扩展名不一样,可以改成你自己的扩展名,注意大小写。 下面的php_zcj.h也是一样,将zcj替换成你的扩展名,注意一个规范,添加到源代码中的函数应该在头文件中声明。
php_zcj.h
#ifndef PHP_ZCJ_H #define PHP_ZCJ_H
externzend_module_entry zcj_module_entry;#define phpext_zcj_ptr &zcj_module_entry#define PHP_ZCJ_VERSION "0.1.0"#define PHP_ZCJ_EXTNAME "zcj"//函数的原型声明,以便建立过程能够正确进行
PHP_FUNCTION(zcj);
PHP_FUNCTION(zcj_long);
PHP_FUNCTION(zcj_double); #万一
接下来就可以编写代码来实现扩展功能了。
具体怎么写,暴露php使用的技巧,在zend_function_entry结构体中添加几行PHP_FE(),第一个参数函数名第二个为Null,函数返回string类型,返回其他类型为a有点不同,所以请注意,我不知道为什么,只知道如何。
还有一些预处理php的扩展,这些无所谓。 不同版本该工具生成的预处理是不同的。
zcj.c
#ifdef HAVE_CONFIG_H#include "config.h"#endif #include "php.h"#include "php_zcj.h" double test(){ return 3.13789; } PHP_FUNCTION(zcj) { zend_string *strg; strg = strpprintf(0, "hello zcj. (from zcj module)"); RETURN_STR(strg); } PHP_FUNCTION(zcj_long) { RETURN_LONG(2001); } PHP_FUNCTION(zcj_double){ RETURN_DOUBLE(test()); }const zend_function_entry zcj_functions[] = { PHP_FE(zcj, NULL) PHP_FE(zcj_long, NULL) PHP_FE(zcj_double, NULL) PHP_FE_END }; zend_module_entry zcj_module_entry = { STANDARD_MODULE_HEADER, PHP_ZCJ_EXTNAME, zcj_functions, NULL, NULL, NULL, NULL, NULL, PHP_ZCJ_VERSION, STANDARD_MODULE_PROPERTIES }; #ifdef COMPILE_DL_ZCJ#ifdef ZTS ZEND_TSRMLS_CACHE_DEFINE()#endif ZEND_GET_MODULE(zcj)#endif
然后
1.phpize初始化
2.生成makefile
3.生成so文件,放到php扩展目录下
phpize
./configure --with-php-config=/usr/local/php/bin/php-config
制作 && 制作安装
然后使用
服务 php-fpm 重新启动
php -r “回显 zcj_long();”
输出成功,函数扩展写入
二、扩展类编译
编写zcjOop的扩展类
mkdir zcjOop cdzcjOop
还是三个文件
配置.m4
PHP_ARG_WITH(zcjOop, for zcjOop support, Make sure that the comment is aligned: [ --with-zcjOop Include zcjOop support])if test "$PHP_ZCJOOP" != "no"; then PHP_NEW_EXTENSION(zcjOop, zcjOop.c, $ext_shared,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1) fi php_zcjOop.h #ifndef PHP_ZCJOOP_H#define PHP_ZCJOOP_Hextern zend_module_entry zcjOop_module_entry;#define phpext_zcjOop_ptr &zcjOop_module_entry#define PHP_ZCJOOP_VERSION "0.1.0"#define PHP_ZCJOOP_EXTNAME "zcjOop"#endif zcjOop.c #ifdef HAVE_CONFIG_H#include "config.h"#endif#include "php.h"#include "php_zcjOop.h" zend_class_entry *zcjOop_ce;//第一个参数是类名,第二个参数是类的方法 PHP_METHOD(zcjOop, learn); PHP_METHOD(zcjOop, znb);
//如果方法需要接受参数,则执行接下来的三句 //ZEND_BEGIN_ARG_INFO_EX的最后一个参数1是传递的参数个数。
ZEND_BEGIN_ARG_INFO_EX(arginfo_zcjOop_learn, 0, 0, 1)//ZEND_ARG_INFO的第一个参数0表示是否通过引用传递。一般默认为0
ZEND_ARG_INFO(0, love) ZEND_END_ARG_INFO() PHP_FUNCTION(zcj_oop) { zval *value=NULL; zend_string *type; if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|z", &type, &value) == FAILURE) { return; } //strg = strpprintf(0, "hello zcj_oop. (from zcj module)"); RETURN_ZVAL(value,0,1);
}constzend_function_entry zcjOop_methods[] = {// 1 类名, // 2 方法名, // 3 zend_arg_info 的参数列表, // 4.访问权限 // ZEND_ACC_PUBLIC ZEND_ACC_PRIVATE ZEND_ACC_PROTECTED 是我们类上面的三个访问权限 // ZEND_ACC_CTOR 标记构造函数 // ZEND_ACC_DTOR 标识析构函数
PHP_ME(zcjOop, learn, arginfo_zcjOop_learn, ZEND_ACC_PUBLIC) PHP_ME(zcjOop, znb, arginfo_zcjOop_learn, ZEND_ACC_PUBLIC) };const zend_function_entry zcj_functions[] = { PHP_FE(zcj_oop, NULL) PHP_FE_END }; PHP_METHOD(zcjOop, learn) { char *love = NULL; //size_t love_len; if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &love) == FAILURE) { return; } // zend_update_property_string(zcjOop_ce,getThis(),"memory",sizeof("memory") - 1, love); } PHP_METHOD(zcjOop, znb) { char *love = NULL; if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &love) == FAILURE) { return; } } PHP_MINIT_FUNCTION(zcjOop) { /* If you have INI entries, uncomment these lines * REGISTER_INI_ENTRIES(); * */ zend_class_entry ce; INIT_CLASS_ENTRY(ce, "zcjOop", zcjOop_methods); zcjOop_ce = zend_register_internal_class(&ce); zend_declare_property_null(zcjOop_ce, "memory",sizeof("memory") - 1, ZEND_ACC_PUBLIC); //返回成功进入下一个事件 return SUCCESS;
}//zend_moduel_entry//扩展模块信息结构体的10个值的每个函数//第一个应该是起始指针,不知道是做什么用的//第三个是函数扩展,如果扩展需要一个函数php的扩展,只需填写一个zend_function_entry结构体变量名//第二个是扩展名。 您可以使用扩展字符列表或 PHP_extension_EXTNAME// PHP_MINIT(myfun); /*当PHP加载时,模块启动的函数被引擎调用。 这会提示引擎做一些初始化如资源类型、注册INI变量等。 */ 1// PHP_MSHUTDOWN(myfun); /* 当PHP完全关闭时,引擎会调用模块关闭函数。 通常用于取消注册 INI 条目 */// PHP_RINIT(myfun); /* 在每个 PHP 请求开始时,调用预请求启动函数。 通常用于管理预请求逻辑。 */// PHP_RSHUTDOWN(myfun); /* 每次PHP请求结束后,调用预请求关闭函数。 在清除请求之前始终应用逻辑来启动函数。 */// PHP_MINFO(myfun); /*调用phpinfo()时会调用模块信息函数,从而将模块信息复制出来。 */// 最后两个应该是一些扩展信息什么的
zend_module_entry zcjOop_module_entry = { STANDARD_MODULE_HEADER, "zcjOop", zcj_functions, PHP_MINIT(zcjOop), NULL, NULL, NULL, NULL, PHP_ZCJOOP_VERSION, STANDARD_MODULE_PROPERTIES };/* }}} */ #ifdef COMPILE_DL_ZCJOOP#ifdef ZTS ZEND_TSRMLS_CACHE_DEFINE();#endif ZEND_GET_MODULE(zcjOop)#endif
发表评论