浅谈PHP Extension的开发——基础篇

 更新时间:2010年12月09日 21:47:38   作者:  
要开发PHP扩展,第一步要下载PHP源代码,因为里面有开发扩展需要的工具。我下载的是PHP最新版本5.3.3,格式为tar.bz2压缩包。

下面是“say_hello.c”中需要编写的info_func的具体代码:

复制代码 代码如下:

/* {{{ PHP_MINFO_FUNCTION
*/
PHP_MINFO_FUNCTION(say_hello)
{
php_info_print_table_start();
php_info_print_table_header(2, "say_hello support", "enabled");
php_info_print_table_row(2, "author", "Zhang Yang"); /* Replace with your name */
php_info_print_table_end();

/* Remove comments if you have entries in php.ini
DISPLAY_INI_ENTRIES();
*/
}
/* }}} */

可以看到我们编写了两行内容、组件是否可用以及作者信息。

编写核心函数
编写核心函数,总共分为三步:1、使用宏PHP_FUNCTION定义函数体;2、使用宏ZEND_BEGIN_ARG_INFO和ZEND_END_ARG_INFO定义参数信息;3、使用宏PHP_FE将函数加入到say_hello_functions中。下面分步说明。

使用宏PHP_FUNCTION定义函数体
复制代码 代码如下:

PHP_FUNCTION(say_hello_func)
{
char *name;
int name_len;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE)
{
return;
}
php_printf("Hello %s!", name);

RETURN_TRUE;
}

上文说过,编写PHP扩展时几乎所有东西都不能裸写,而是必须使用相应的宏。从上面代码可以清楚看到这一点。总体来说,核心函数代码一般由如下几部分构成:

定义函数,这一步通过宏PHP_FUNCTION实现,函数的外部名称就是宏后面括号里面的名称。

声明并定义局部变量。

解析参数,这一步通过zend_parse_parameters函数实现,这个函数的作用是从函数用户的输入栈中读取数据,然后转换成相应的函数参数填入变量以供后面核心功能代码使用。zend_parse_parameters的第一个参数是用户传入参数的个数,可以由宏“ZEND_NUM_ARGS() TSRMLS_CC”生成;第二个参数是一个字符串,其中每个字母代表一个变量类型,我们只有一个字符串型变量,所以第二个参数是“s”;最后各个参数需要一些必要的局部变量指针用于存储数据,下表给出了不同变量类型的字母代表及其所需要的局部变量指针。

image

参数解析完成后就是核心功能代码,我们这里只是输出一行字符,php_printf是Zend版本的printf。

最后的返回值也是通过宏实现的。RETURN_TRUE宏是返回布尔值“true”。

使用宏ZEND_BEGIN_ARG_INFO和ZEND_END_ARG_INFO定义参数信息

参数信息是函数所必要部分,这里不做深究,直接给出相应代码:

复制代码 代码如下:

ZEND_BEGIN_ARG_INFO(arginfo_say_hello_func, 0)
ZEND_END_ARG_INFO()

如需了解具体信息请阅读相关宏定义。

使用宏PHP_FE将函数加入到say_hello_functions中
最后,我们需要将刚才定义的函数和参数信息加入到say_hello_functions数组里,代码如下:
复制代码 代码如下:

const zend_function_entry say_hello_functions[] = {
PHP_FE(say_hello_func, arginfo_say_hello_func)
{NULL, NULL, NULL}
};

这一步就是通过PHP_EF宏实现,注意这个数组最后一行必须是{NULL, NULL, NULL} ,请不要删除。

下面是编写完成后的say_hello.c全部代码:
复制代码 代码如下:

/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2010 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: |
+----------------------------------------------------------------------+
*/

/* $Id: header 297205 2010-03-30 21:09:07Z johannes $ */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "php.h"
#include "php_ini.h"
#include "ext/standard/info.h"
#include "php_say_hello.h"

/* If you declare any globals in php_say_hello.h uncomment this:
ZEND_DECLARE_MODULE_GLOBALS(say_hello)
*/

/* True global resources - no need for thread safety here */
static int le_say_hello;

/* {{{ PHP_FUNCTION
*/
PHP_FUNCTION(say_hello_func)
{
char *name;
int name_len;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE)
{
return;
}
php_printf("Hello %s!", name);

RETURN_TRUE;
}

ZEND_BEGIN_ARG_INFO(arginfo_say_hello_func, 0)
ZEND_END_ARG_INFO()
/* }}} */

/* {{{ say_hello_functions[]
*
* Every user visible function must have an entry in say_hello_functions[].
*/
const zend_function_entry say_hello_functions[] = {
PHP_FE(say_hello_func, arginfo_say_hello_func)
{NULL, NULL, NULL} /* Must be the last line in say_hello_functions[] */
};
/* }}} */

/* {{{ say_hello_module_entry
*/
zend_module_entry say_hello_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
STANDARD_MODULE_HEADER,
#endif
"say_hello",
say_hello_functions,
NULL,
NULL,
NULL,
NULL,
PHP_MINFO(say_hello),
#if ZEND_MODULE_API_NO >= 20010901
"0.1", /* Replace with version number for your extension */
#endif
STANDARD_MODULE_PROPERTIES
};
/* }}} */

#ifdef COMPILE_DL_SAY_HELLO
ZEND_GET_MODULE(say_hello)
#endif

/* {{{ PHP_MINFO_FUNCTION
*/
PHP_MINFO_FUNCTION(say_hello)
{
php_info_print_table_start();
php_info_print_table_header(2, "say_hello support", "enabled");
php_info_print_table_row(2, "author", "Zhang Yang"); /* Replace with your name */
php_info_print_table_end();

/* Remove comments if you have entries in php.ini
DISPLAY_INI_ENTRIES();
*/
}
/* }}} */

编译并安装扩展
在say_hello目录下输入下面命令:
复制代码 代码如下:

/usr/bin/phpize
./configure
make
make install

这样就完成了say_hello扩展的安装(如果没有报错的话)。

这时如果你去放置php扩展的目录下,会发现多了一个say_hello.so的文件。如下图所示:

image

下面就是将其加入到php.ini配置中,然后重启Apache(如果需要的话)。这些都是PHP基本配置的内容,我就不详述了。

扩展测试

如果上面顺利完成,这时运行phpinfo(),应该能看到如下信息:

image

这说明扩展已经安装成功了。然后我们编写一个测试用PHP脚本:

复制代码 代码如下:

<?php
say_hello_func('Zhang Yang');
?>

执行这个脚本,结果如下:

image

说明扩展已经正常工作了。

总结

这篇文章主要用示例方法介绍PHP Extension的开发基础。在PHP的使用中,也许是因为需要支持新的组件(如新的数据库),又或是业务需要或性能需要,几乎都会遇到需要开发PHP扩展的地方。后续如果有机会,我会写文章介绍一些关于扩展开发较为深入的东西,如扩展模块生命周期、INI使用以及编写面向对象的扩展模块等等。
本文基于署名-非商业性使用 3.0许可协议发布,欢迎转载或演绎,但是必须保留本文的署名张洋(包含链接),且不得用于商业用途。如您有任何疑问或者授权方面的协商,请与我联系

相关文章

  • PHP7常量数组用法分析

    PHP7常量数组用法分析

    这篇文章主要介绍了PHP7常量数组用法,结合实例形式分析了php7常量数组的功能、定义与使用方法,需要的朋友可以参考下
    2016-09-09
  • php短域名转换为实际域名函数

    php短域名转换为实际域名函数

    现在很多朋友需要将实际域名转换为短域名,但也有朋友需要反转查看下实际域名,那么就可以使用这个函数。
    2011-01-01
  • PHP中防止SQL注入方法详解

    PHP中防止SQL注入方法详解

    这篇文章主要介绍了PHP中防止SQL注入方法详解,需要的朋友可以参考下
    2014-12-12
  • PHP 杂谈《重构-改善既有代码的设计》之一 重新组织你的函数

    PHP 杂谈《重构-改善既有代码的设计》之一 重新组织你的函数

    我把我比较喜欢的和比较关注的地方写下来和大家分享。上次我写了篇《php 跟老大的对话》。还是有很多疑问,这书帮了我不少的忙
    2012-04-04
  • PHP对象相关知识总结

    PHP对象相关知识总结

    这篇文章主要介绍了PHP对象相关知识总结的相关资料,需要的朋友可以参考下
    2017-04-04
  • 解决PHP字符串长度不一致的问题

    解决PHP字符串长度不一致的问题

    下面小编就为大家分享一篇解决PHP字符串长度不一致的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2017-12-12
  • PHP实现LRU算法的示例代码

    PHP实现LRU算法的示例代码

    LRU是Least Recently Used 近期最少使用算法, 内存管理的一种页面置换算法。本文将详解LRU算法的原理以及实现,感兴趣的小伙伴可以学习一下
    2022-06-06
  • php学习笔记之面向对象编程

    php学习笔记之面向对象编程

    一个php初学者的一个学习笔记的面向对象编程实例,有需要学习的朋友可参考下,脚本之家也更新了很多大家可以查阅下
    2012-12-12
  • 推荐十款免费 WordPress 插件

    推荐十款免费 WordPress 插件

    本文给大家介绍的是今年必备的10款WordPress插件,非常的实用,包含WordPress SEO By Yoast,Akismet,W3 Total Cache,Disqus Comment System,Google Sitemap Generator,Jetpack,Limit Login Attempts,Contact Form 7,Yet Another Related Posts Plugin等
    2015-03-03
  • php flush无效,IIS7下php实时输出的方法

    php flush无效,IIS7下php实时输出的方法

    这篇文章主要介绍了php flush无效,IIS7下php实时输出的方法,需要的朋友可以参考下
    2016-08-08

最新评论