Php extension开发

35
ianzhang

description

 

Transcript of Php extension开发

ianzhang

What is Extensionstandard extension

自定义 extension

What is Extensionapc, mysqli 等都是 extension默认放在 /usr/local/php/lib/php/extensions/no-

debug-non-zts-20060613 中在 php.ini 中开启需要的 extension

Extension能做什么和不同业务交互,接口是 C/C++ 接口,我们需要

extension 从 php 和这些接口交 互,协议接口使用 extension 和共享内存交互,和高性能 c 程序完成高性能工作 - 数据库异步写操作利用 c 的运算速度,完成高性能算法在 php 中的实现 将之前必须在 c 的环境下的工作,转移到 php 中 – 高性能 server 在 php 中的开发

今天的目标Hello World一个简单的加法运算函数

开发环境Linux 系统autoconfigphp 源码安装好的 php 环境

That‘s All ! Easy

PHP程序生命周期

Apache PHP子进程

Begin所有 extension 的编译环境都放在源代码的 Ext 子目录下 使用自动构建系统 ./ext_skel --extname = my_module 创建了名为 my_module 的文件夹

config.m4用于 Autoconfig, 用 m4 文件来处理宏生成需要的

configure 文件config.m4 文件负责在配置时解析 configure 的命令行选项 在 config.m4 中 dnl 表示注释

config.m4PHP_ARG_WITH 和 PHP_ARG_ENABLE 指定

了 PHP 扩展模块的工作方式,前者意味着不需要第三方库,后者正好相反 if test "$PHP_MY_MODULE" != "no“PHP_ADD_INCLUDE 指定 PHP 扩展模块用到的头文件目录 PHP_SUBST(MY_MODULE_SHARED_LIBAD

D) 用于说明这个扩展编译成动态链接库的形式

C -> C++PHP core 是用 c 编写的,使用 c++ 的时候,需要

在 config.m4 中增加参数PHP_REQUIRE_CXX()PHP_ADD_LIBRARY(stdc++,"",MY_MODULE_SHARED_LIBADD)

PHP_NEW_EXTENSION(my_module, “my_module.cpp", $ext_shared)

修改 .c 变成 .cpp

C -> C++对于 ext_skel 生成的代码使用 extern “c” 来兼容纯 c 的代码

注:因为不同的编译器可能生成不同的中间符号名,所以用 extern 来修饰,具体参见 http://www.cppblog.com/Macaulish/archive/2008/06/17/53689.html

Add function打开 php_my_module.h找到 PHP_FUNCTION ,增加一行

PHP_FUNCTION(my_module_test);

打开 my_module.cpp搜索 PHP_FE ,增加一行

PHP_FE(my_module_test, NULL)增加 PHP_FUNCTION(my_module_test)

Coding functionZEND 的编程使用大量的宏,手册和对宏的了解是必不可少的OutputInputHandleReturn

Output使用 zend_printf 函数完成 outputzend_error(E_ERROR, “xxx” ) 错误输出 E_ERROR E_WARNING E_NOTICE E_CORE_ERROR E_COMPILE_ERROR E_COMPILE_WARNING

InputZEND_NUM_ARGS () 取得传入参数数量WRONG_PARAM_COUNT 抛出参数错误,终止程序

Input使用 zend_parse_parameters 来取得参数

第一个参数表示需要解析的个数,可以使用 ZEND_NUM_ARGS() 来表示对传入的参数“有多少要多少”。

type_spec 是一个字符串,用来指定各个参数的类型,类似于 printf 中的参数格式化 ,当然后面的就是类似的变参,但是注意这里全部要使用参数的指针来获取

Input参数类型 l - 长整数 d - 双精度浮点数 s - 字符串 ( 也可能是空字节 ) 和其长度 b - 布尔值 r - 资源 , 保存在 zval* a - 数组 , 保存在 zval* o - (任何类的)对象 , 保存在 zval* O - (由 class entry 指定的类的)对象 , 保存在 zval* z - 实际的 zval*

| - 表明剩下的参数都是可选参数。如果用户没有传进来这些参数值,那么这些值就会被初始化成默认值。 / - the parsing function will call SEPARATE_ZVAL_IF_NOT_REF() on the

parameter it follows, to provide a copy of the parameter, unless it's a reference

! - the parameter it follows can be of specified type or NULL (仅用在 a 、 o 、 O 、 r 和 z 身上)。如果用户传进来了一个 NULL 值,则存储该参数的变量将会设置为 NULL 。

Input Sample1

Input Sample2

HandleExension 中处理部分最特殊的部分就是 php

extension 中 c 的变量如何被 php 代码使用两种交互方法

创建一个变量,加到 php 的变量容器中创建一个变量,返回这个变量

PHP访问 Zend变量创建 zval 容器对 zval结构进行填充把 zval引入 zend 的内部符号表中从 php端访问

变量作用域全局变量 &EG(symbol_table) 局部变量 EG(active_symbol_table)

使用局部变量的时候要注意陷阱和段错误

加入符号表效率宏 ZNED_SET_SYMBOL 首先检查变量是否已经存在于符号表中,如果已经存在则将其转换为一个引用变量(同时会自动销毁原有的 zval 容器)。速度较慢,节省内存zend_hash_update 函数 强制更新符号表,速度较快,内存消耗稍多

变量赋值zval结构

value 存放 zval 的值, type 存放类型zval赋值

不同变量类型IS_LONG IS_DOUBLE IS_STRING IS_BOOL

数组变量赋值数组在 Zend 内部是用哈希表( HashTable )来存储的array_init(zval*) 来进行数组的初始化使用 add_assoc_*() 和 add_index_*() add_assoc_long(zval *array, char *key, long n); add_assoc_string(zval *array, char *key, char *str, int

duplicate); add_index_long(zval *array, uint idx, long n); add_index_string(zval *array, uint idx, char *str, int

duplicate);

数组变量赋值因为数组变量是用 hash 表来管理的,使用 zend_hash_update(new_array->value.ht, key,

strlen(key) + 1, (void *)&new_element, sizeof(zval *), NULL)

zend_hash_index_update(new_array->value.ht, key, (void *)&new_element, sizeof(zval *), NULL)

对象变量Object like Arrayobject_init() 初始化对象使用 add_property_*() 函数 add_property_long(zval *object, char *key, long l); add_property_string(zval *object, char *key, char *str, int

duplicate); add_property_bool(zval *object, char *key, int b);

Return返回值都是通过为 return_value 的变量传递的。这个参数是一个已经申请好空间的 zval 容器,无需先对 return_value 执行 MAKE_STD_ZVAL 宏指令。

Return使用 RETURN_* 和 RETVAL_* 宏来完成RETURN_BOOL(bool)返回一个布尔值。 RETURN_NULL()返回一个空值。 RETURN_LONG(long)返回一个长整数。RETVAL_LONG(long)设定返回值为指定的一个长整数。 RETVAL_DOUBLE(double)设定返回值为指定的一个双精度浮点数。 RETVAL_STRING(string, duplicate)

More to learnExtension 运行模式内存管理资源控制Class …..

ReferenceZend API

http://yanbin.org/archive/php-manual-hacking-the-code-of-php.html

Extension Writing http://devzone.zend.com/article/1021http://my.huhoo.net/archives/2008/06/linu

xcphp.htmlGOOGLEPHP.NET

Thank You