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)所有,未经作者本人同意禁止任何形式的转载,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。

第一个有点作用的PHP扩展的更多相关文章

  1. Linux下脚本文件第一行的作用

    Linux下脚本文件第一行的作用 在Linux/Unix系统中,你可以在脚本hello.py顶部添加以下命令让Python脚本可以像SHELL脚本一样可直接执行: #! /usr/bin/env py ...

  2. 安全测试6_Web安全工具第一节(浏览器入门及扩展)

    今天来学习下浏览器的功能,浏览器是我们经常用到但是功能却很强大的一个东东,我们经常用到的无非是三种(谷歌.火狐.IE) 1.浏览器功能介绍: 下面以谷歌浏览器(Chrome版本为56)为例,介绍下,懂 ...

  3. PHP扩展开发(1):入门

    有关PHP扩展开发的文章.博客已经很多了,比较经典的有: TIPI项目(http://www.php-internals.com/,强烈推荐) <Extending and Embedding ...

  4. Struts2第一天

    Struts2第一天 整体课程安排:3天知识点+2天练习 第一天:入门(action和result结果集)--一般的请求+响应 第二天:请求数据处理相关(参数接收.类型转换.合法性校验.国际化) 第三 ...

  5. SQL Server 扩展事件(Extented Events)从入门到进阶(4)——扩展事件引擎——基本概念

    本文属于 SQL Server 扩展事件(Extented Events)从入门到进阶 系列 在第一二节中,我们创建了一些简单的.类似典型SQL Trace的扩展事件会话.在此过程中,介绍了很多扩展事 ...

  6. C#编程(六十一)------------LINQ中的扩展方法

    原文链接: http://blog.csdn.net/shanyongxu/article/details/47208401 LINQ中的扩展方法 LINQ中where扩展方法,要想使用,必须导入us ...

  7. php扩展开发-快速上手

    系统环境CentOS release 6.5 (Final) PHP版本php-5.6.27 扩展开发需要有php环境及php的源代码,我的PHP安装目录/home/zhangxiaomin/stud ...

  8. XAML实例教程系列 - 标记扩展(Markup Extensions) 六

    XAML实例教程系列 - 标记扩展(Markup Extensions) 分类: Windows 8 Silverlight2012-06-21 13:00 1139人阅读 评论(0) 收藏 举报 扩 ...

  9. Mysql优化(出自官方文档) - 第一篇(SQL优化系列)

    Mysql优化(出自官方文档) - 第一篇 目录 Mysql优化(出自官方文档) - 第一篇 1 WHERE Clause Optimization 2 Range Optimization Skip ...

随机推荐

  1. GET请求参数为中文时乱码分析

    问题描述 近期做任务时,跟后端联调时遇到一个问题,前端发送get请求,当参数值有中文时,请求失败,请求参数变为乱码.(ps:一般当参数有中文时,很少使用get请求,而是使用post请求来传输数据,请求 ...

  2. 实现Linux与Windows下一致的命令行

    这其实是个非常简单的东西. 我们会写一些命令行的工具,一般跨平台的话,会用python或者perl写,比如叫foo.py,然后在Windows和Linux下调用这个脚本: Linux: foo.py ...

  3. 学习笔记——Maven 如何处理传递性依赖

    maven引入的传递性依赖机制,一方面大大简化和方便了依赖声明,另一方面,大部分情况下我们只需要关心项目的直接依赖是什么,而不用考虑这些直接依赖会引入什么传递性依赖.但有时候,当传递性依赖造成问题的时 ...

  4. 网游中的网络编程系列1:UDP vs. TCP

    原文:UDP vs. TCP,作者是Glenn Fiedler,专注于游戏网络编程相关工作多年. 目录 网游中的网络编程系列1:UDP vs. TCP 网游中的网络编程2:发送和接收数据包 网游中的网 ...

  5. NetworkSocket结构图

    分层思想 NetworkSocket使用分层的思想,分基础层和上层: 1.基础层提供基础通讯,重要的对象有SessionBase.TcpServerBase和TcpClientBase: 2.上层实现 ...

  6. Linux C中结构体初始化

          在阅读GNU/Linux内核代码时,我们会遇到一种特殊的结构初始化方式.该方式是某些C教材(如谭二版.K&R二版)中没有介绍过的.这种方式称为指定初始化(designated in ...

  7. 爬虫获取邮箱,存入数据库,发送邮件java Mail

    在网页上获取邮箱: package com.my.test; import java.io.BufferedReader; import java.io.InputStreamReader; impo ...

  8. innerHeight,clientHeight,offsetHeight,scrollWidth等的区别和用法

    要理解这几个属性,首先要搞明白body,documentElement的区别 1.body是DOM对象里的body子节点,即<body>标签2.documentElement是整个节点树的 ...

  9. nginx location语法使用说明

    语法规则: location [=|~|~*|^~] /uri/ { … } = 开头表示精确匹配 ^~ 开头表示uri以某个常规字符串开头,理解为匹配 url路径即可.nginx不对url做编码,因 ...

  10. 由 excel 转换为 markdown,及收获

    由 excel 转换为 markdown,及收获 1 问题 构建之法(现代软件工程)东北师大站[http://www.cnblogs.com/younggift/]的每周学生作业成绩,执行教学团队[h ...