这里主要讲述在PHP及Zend框架下怎么使用Zend API和C++语言来实现自己所要的功能以及项目的开发。
此篇文章所运用的环境在Linux 2.4.21-4.ELsmp(Red Hat Linux
3.2.3-20),Apache/2.2.8,gcc version 3.2.3 20030502,PHP 5.2.5 (cli),Zend
Engine v2.2.0下进行。
前言
上次我们说到使用c++写一个完整的php扩展,这里以ext_name模块为例复习一下:
首先仍然修改config.m4文件,由于没有引用外面的模块或者相关库,所以不需要使用PHP_ARG_WITH的方式,使用PHP_ARG_ENABLE方式。找到
PHP_NEW_EXTENSION(ext_name, ext_name.c, $ext_shared)
修改成
PHP_REQUIRE_CXX()
PHP_ADD_LIBRARY(stdc++, "", EXTRA_LDFLAGS)
PHP_NEW_EXTENSION(ext_name, ext_name.cpp, $ext_shared)
并将ext_name.c重新命名为ext_name.cpp,接着修改其内容,将
#include "php.h"
#include "php_ini.h"
#include "ext/standard/info.h"
用extern "C"将其用大括号括起来,修改
ZEND_GET_MODULE(ext_name)
为
BEGIN_EXTERN_C()
ZEND_GET_MODULE(ext_name)
END_EXTERN_C()
到此为止,这就是我们第一章内容,第二章比较庞大,这里还是分节来叙述吧。
概述
概述里面主要简单介绍PHP扩展中的一些大致结构和需要注意的事项,做过C扩展PHP的都会知道 PHP_FE是一个宏把这个宏标识的函数,例如:helloworld,这个函数可以直接作用于PHP解释器,比如
<?php
helloworld();
?>
安装ext_name样板后,系统会自动有一个函数confirm_ext_name_compiled,这个函数是可以自行修改的,当然,PHP_FE可以定义多个函数,这些函数都必须在之前进行申明,一般在php_ext_name.h头文件进行申明。
我们还知道,仅仅有头文件和PHP_FE宏来申明这个函数是不行的,这个函数还没有内容,怎么编写这个函数的内容呢?这个在接下来会讲到。
其实,稍微细心的人看了ext_name.cpp就知道,去掉注释后,还有很多的宏命令,比如zend_module_entry、ZEND_GET_MODULE、PHP_MINIT_FUNCTION等等,读者不要着急,下面会一一道来。
关于ext_name.cpp文件中一些变量的命名,通常是PHP模块名(eg:ext_name)前面或者后面有一串字符,比如 le_ext_name、ext_name_functions、这是一种习惯,最好我们在书写的时候遵循这种习惯,这样写出来的代码不仅仅让你自己明 白,让其他的开发人员也能够很快熟悉你的代码。通常一些定义的常量会大写,比如要定义这个模块的名字和版本,可以在头文件中添加:
#define PHP_EXT_NAME_EXTNAME "ext_name"
#define PHP_EXT_NAME_VERSION "0.1"
然后修改ext_name_module_entry的内容,将"ext_name"和"0.1"分别用PHP_EXT_NAME_EXTNAME和PHP_EXT_NAME_VERSION来替换,这样具有方便且通用。
如果你可能在代码中可能需要用到stl之类的或者c++的一些库,那么你可以在ext_name.cpp文件中添加
#ifndef __APP_CPP__
#define __APP_CPP__
#include <iostream>
#include <fstream>
#include <string>
/*
#include <sstream>
#include <list>
#include <vector>
#include <map>
#include <hashmap>
#include <set>
#include <bitset>
*/
#endif
PHP 与 Zend API
引用一句经典的原文来说明PHP和Zend API之间的关系
PHP的核心由两部分组成。最底层是Zend引擎(ZE)。ZE把人类易读的脚本解析成机器可读的符号,
然后在进程空间内执行这些符号。ZE也处理内存管理、变量作用域及调度程序调用。另一部分是PHP内核,
它绑定了SAPI层(Server Application Programming Interface,通常涉及主机环境,如Apache,IIS,CLI,CGI等),
并处理与它的通信。它同时对safe_mode和open_basedir的检测提供一致的控制层,就像流层将fopen()、fread()和
fwrite()等用户空间的函数与文件和网络I/O联系起来一样。
模块信息
模块信息主要体现在ext_name_module_entry结构上,它包含了
1, 标准模块的头
通常用 "STANDARD_MODULE_HEADER" 来填充,它指定了模块的四个成员:
- 标识整个模块结构大小的 size
- 值为 ZEND_MODULE_API_NO 常量的 zend_api
- 标识是否为调试版本(使用 ZEND_DEBUG 进行编译)的 zend_debug
- 还有一个用来标识是否启用了 ZTS (Zend 线程安全,使用 ZTS 或USING_ZTS 进行编译)的 zts。
2, 模块名称
模块名称这个名字就是使用 phpinfo() 函数后在“Additional Modules”部分所显示的名称。
3, PHP扩展可用到的函数或类
zend函数块的指针
4, 模块启动函数
5, 模块关闭函数
6, 请求启动函数
7, 请求关闭函数
8, 模块信息函数
9, 模块的版本号
10, 其它结构元素
(待续)