Home >Backend Development >PHP Tutorial >第一个有些作用的PHP扩展

第一个有些作用的PHP扩展

WBOY
WBOYOriginal
2016-06-13 12:20:08988browse

第一个有点作用的PHP扩展

C/C++去开发PHP扩展

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

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

php扩展函数前奏

首先生成”骨架“:
<code>1. 进入php源码src/ext目录下面2. 运行./ext_skel --extname=mytest3. 进入src/ext/mytest/目录4. 在编写扩展的时候要先修改下config.me文件的10-12行,去掉前面的dnl注释,这个网上一搜一大把。</code>
在头文件php_mttest.h中声明要编写的php扩展函数名
<code>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行</code>

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

<code>void zif_get_log_title( int ht, zval *return_value, zval **return_value_ptr, zval *this_ptr, int return_value_used TSRMLS_DC)</code>
在mytest.c中的zend_function_entry声明中添加get_log_title函数的声明
<code>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);}</code>

这里还要看个宏RETURN_STRING

<code>#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)</code>

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

<code>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;	}</code>
编译测试
<code>编译的时候需要安装好的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());'</code>

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

<code>[[email protected] logs]# php -r 'var_dump(get_log_title());' && datestring(39) "[2015-05-19 22:52:29 1432047149.755613]"2015年 05月 19日 星期二 22:52:29 CST</code>

5/19/2015 10:54:38 PM

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

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn