php扩展的实现

php的扩展实现后,有两种形态,一种是新扩展一个方法,还有一种是扩展一个类。
php版本是php7
一、扩展方法
准备好代码目录

mkdir zcj
cd zcj

新建三个文件就是靠这三个文件来生成扩展(也有工具可以自动生成,具体看参考文章)

//php_扩展名,扩展名.c  **规范要注意**
config.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


extern zend_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);
#endif

接下来就可写实现扩展的功能代码了
具体是怎么写呢,要暴露给php使用的方法要在zend_function_entry结构体中添加对应的几行PHP_FE(),第一个参数函数名字第二个是Null,返回字符串类型的函数跟返回其他类型有点不一样,要注意一下,我也不知道why,只能how了。
还有一些预处理,这些不用管。不同版本用工具生成的预处理都不同。
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
 make && make install

然后用

service php-fpm restart
php -r "echo zcj_long();"

成功输出,函数扩展就写好了
二、扩展类编写
编写一个zcjOop的扩展类

mkdir zcjOop 
cd zcjOop

还是三个文件
config.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_H
extern 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);
}
const zend_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个值的各个作用
//第一个应是一个启动指针吧,不知道是干嘛的
//第三个是函数扩展,如果扩展需要函数,就填上一个zend_function_entry结体构变量名
//第二个是扩展名你可以用扩展名字符数组也可以用PHP_扩展名_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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值