• 第一个有点作用的PHP扩展


    C/C++去开发PHP扩展

    我觉的对于PHP开发人员来说,学的东西非常杂,也非常多,当然了开发PHP扩展也是一个必须要掌握的技能,这里膜拜下大神鸟哥(Laruence)~
    今天要开发的第一个有点功能的扩展,主要作用是记录日志的时候生成日志前面的日期部分

    #即使当前的时间,年-月-日 时:分:秒 时间戳.微妙数 
    [2015-05-19 20:39:32 1432039172.968199]
    

    php扩展函数前奏

    首先生成”骨架“:
    1. 进入php源码src/ext目录下面
    2. 运行./ext_skel --extname=mytest
    3. 进入src/ext/mytest/目录
    4. 在编写扩展的时候要先修改下config.me文件的10-12行,去掉前面的dnl注释,这个网上一搜一大把。
    
    在头文件php_mttest.h中声明要编写的php扩展函数名
    PHP_FUNCTION(get_log_title);
    #PHP_FUNCTION是PHP内核中声明的一个宏
    #define PHP_FUNCTION 		ZEND_FUNCTION    //在文件src/main/php.h : 347行
    #define ZEND_FUNCTION(name) ZEND_NAMED_FUNCTION(ZEND_FN(name))		//文件src/Zend/zend_API.h : 68行
    #define ZEND_FN(name) 		zif_##name		//文件src/Zend/zend_API.h : 65行
    #define ZEND_NAMED_FUNCTION(name) void name(INTERNAL_FUNCTION_PARAMETERS)	//文件src/Zend/zend_API.h : 67行
    #define INTERNAL_FUNCTION_PARAMETERS int ht, zval *return_value, zval **return_value_ptr, zval *this_ptr, int return_value_used TSRMLS_DC	//src/Zend/zend.h : 290行
    

    上面的声明函数宏展开后是:

    void zif_get_log_title( int ht, zval *return_value, zval **return_value_ptr, zval *this_ptr, int return_value_used TSRMLS_DC)
    
    在mytest.c中的zend_function_entry声明中添加get_log_title函数的声明
    const zend_function_entry logs_functions[] = {
            PHP_FE(confirm_logs_compiled,   NULL)           /* For testing, remove later. */
    		PHP_FE(get_log_title, NULL)
            PHP_FE_END      /* Must be the last line in logs_functions[] */
    };
    #编写函数
    PHP_FUNCTION(get_log_title)
    {
        struct timeval tv;
        time_t rawtime;
        struct tm *timeinfo;
        char *formatinfo;
        time(&rawtime);
        timeinfo = localtime(&rawtime);
        gettimeofday(&tv, NULL);
        spprintf(&formatinfo, 0, "[%4d-%02d-%02d %d:%d:%d %d.%d]", 1900 + timeinfo->tm_year, 1 + timeinfo->tm_mon, timeinfo->tm_mday, timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec, tv.tv_sec, tv.tv_usec);
        RETURN_STRING(formatinfo, 1);
    }
    

    这里还要看个宏RETURN_STRING

    #define RETURN_STRING(s, duplicate) 	{ RETVAL_STRING(s, duplicate); return; }		//文件src/Zend/zend_API.h : 635行
    #define RETVAL_STRING(s, duplicate) 	ZVAL_STRING(return_value, s, duplicate)			//文件src/Zend/zend_API.h : 623行
    #define ZVAL_STRING(z, s, duplicate) do {		//文件src/Zend/zend_API.h : 577-583行,这个的作用其实是给一个string类型zval变量赋值
    	const char *__s=(s);						
    	zval *__z = (z);					
    	Z_STRLEN_P(__z) = strlen(__s);				//设置zval字符串长度
    	Z_STRVAL_P(__z) = (duplicate?estrndup(__s, Z_STRLEN_P(__z)):(char*)__s);	//设置zval字符串的值
    	Z_TYPE_P(__z) = IS_STRING;					//设置zval字符串的类型为字符串
    } while (0)
    

    因此,RETURN_STRING(formatinfo, 1)展开后为:

    do {
    	const char *__s=(formatinfo);
    	zval *__z = (return_value);			//这里面的return_value估计是内核定义的,类似 zval *return_value;
    	(*__z).value.str.len = strlrn(__s);		//等价于__z->value.str.len
    	(*__z).value.str.val = (1?estrndup(__s, (*__z).value.str.len):(char*)__s);
    	(*__z).type = 6;	
    }
    
    编译测试
    编译的时候需要安装好的php,比如我的php安装在/usr/local/php/目录下面
    
    cd mytest;		//今日刚才编写的函数扩展目录
    /usr/local/php/bin/phpize 	//运行phpize,生成configure文件
    ./configure --with-php-config=/usr/local/php/bin/php-config 	//configure,后面的--with-php-config会生成so文件到安装好的扩展目录,当然也可以不用加,声称之后手动copy过去
    make	//有错误的话修正
    make install 	//运行之后会提示类似下面的内容
    #Installing shared extensions:     /usr/local/php/lib/php/extensions/no-debug-non-zts-20100525/
    #修改配置文件php.ini添加extension = mytest.so
    #测试
    php -r 'var_dump(log_get_title());'
    

    输出下面内容的话,恭喜你成功了

    [root@iforever logs]# php -r 'var_dump(get_log_title());' && date
    string(39) "[2015-05-19 22:52:29 1432047149.755613]"
    2015年 05月 19日 星期二 22:52:29 CST
    

    5/19/2015 10:54:38 PM

    本文版权归作者iforever(luluyrt@163.com)所有,未经作者本人同意禁止任何形式的转载,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    实验六
    派生类构造函数的理解
    实验五
    随机数
    面向行的输入(随时添加新的理解)
    实验四
    循序渐进VUE+Element 前端应用开发(21)--- 省市区县联动处理的组件使用(转载)
    循序渐进VUE+Element 前端应用开发(20)--- 使用组件封装简化界面代码(转载)
    循序渐进VUE+Element 前端应用开发(19)--- 后端查询接口和Vue前端的整合(转载)
    循序渐进VUE+Element 前端应用开发(18)--- 功能点管理及权限控制 (转载)
  • 原文地址:https://www.cnblogs.com/iforever/p/4515482.html
Copyright © 2020-2023  润新知