[转]自己写PHP扩展之创建一个类
原文:http://www.imsiren.com/archives/572
比如我们要创建一个类..PHP代码如下
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
class Person { public $name; public $age; public function __construct() { echo "construct is running!"; } public function __destruct() { echo "destruct is running!"; } public function getproperty($key) { echo $this->$key; } public function setproperty($key,$val) { $this->$key = $val; }} |
用PHP来做,很简单..
那么用PHP扩展来写该怎么做?
OK.
1.在php_siren.h里面声明类
|
1
2
3
4
|
PHP_METHOD(Person,__construct);PHP_METHOD(Person,__destruct);PHP_METHOD(Person,setproperty);PHP_METHOD(Person,getproperty); |
PHP_METHOD宏.
PHP_METHOD 等于ZEND_METHOD
这个宏接受两个参数,第一个是类名,第二个是类的方法
|
1
2
3
4
|
#define ZEND_METHOD(classname, name) ZEND_NAMED_FUNCTION(ZEND_MN(classname##_##name))#define INTERNAL_FUNCTION_PARAMETERS int ht, zval *return_value, zval **return_value_ptr, zval *this_ptr, int return_v alue_used TSRMLS_DC//最后等于void name(int ht, zval *return_value, zval **return_value_ptr, zval *this_ptr, int return_v alue_used TSRMLS_DC ) |
这个宏是用来声明我们的方法…
2.设置接收的参数
我们的方法如果需要接受参数.那么就要执行
|
1
2
3
|
ZEND_BEGIN_ARG_INFO_EX(arg_person_info,0,0,2) ZEND_ARG_INFO(0,name)ZEND_END_ARG_INFO() |
详细讲这几个宏之前先看看zend_arg_info
|
1
2
3
4
5
6
7
8
9
10
11
|
typedef struct _zend_arg_info { const char *name; //参数名称 zend_uint name_len;//长度 const char *class_name; //所属类名 zend_uint class_name_len; //类名长度 zend_bool array_type_hint; zend_bool allow_null; //允许为空 zend_bool pass_by_reference; //引用传值 zend_bool return_reference; //引用返回 int required_num_args; //参数个数} zend_arg_info; |
ZEND_BEGIN_ARG_INFO_EX定义在Zend/zend_API.h
|
1
2
3
|
#define ZEND_BEGIN_ARG_INFO_EX(name, pass_rest_by_reference, return_reference, required_num_args) \ static const zend_arg_info name[] = { \ { NULL, 0, NULL, 0, 0, 0, pass_rest_by_reference, return_reference, required_num_args }, |
很明显 声明一个zend_arg_info的数组name,然后初始化结构体的值
ZEND_ARG_INFO(0,name)的定义如下
|
1
|
#define ZEND_ARG_INFO(pass_by_ref, name) { #name, sizeof(#name)-1, NULL, 0, 0, 0, pass_by_ref, 0, 0 }, |
这三个宏 执行代码 等于
|
1
2
3
|
static const zend_arg_info name[] = { { NULL, 0, NULL, 0, 0, 0, pass_rest_by_reference, return_reference, required_num_args },{ #name, sizeof(#name)-1, NULL, 0, 0, 0, pass_by_ref, 0, 0 },}; |
3.创建zend_function_entry结构数组
|
1
2
3
4
5
6
7
|
const zend_function_entry person_functions[]={ PHP_ME(Person,__construct,NULL,ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(Person,__destruct,NULL,ZEND_ACC_PUBLIC|ZEND_ACC_DTOR) PHP_ME(Person,getproperty,arg_person_info,ZEND_ACC_PUBLIC) PHP_ME(Person,setproperty,arg_person_info,ZEND_ACC_PUBLIC) PHP_FE_END}; |
zend_function_entry定义如下
|
1
2
3
4
5
6
7
|
typedef struct _zend_function_entry { const char *fname; //函数名称 void (*handler)(INTERNAL_FUNCTION_PARAMETERS); const struct _zend_arg_info *arg_info;//参数 zend_uint num_args;//参数个数 zend_uint flags;//标示PUBLIC ?PRIVATE ?PROTECTED} zend_function_entry; |
PHP_ME宏接收四个参数
1 类名,
2 方法名,
3 zend_arg_info 的参数列表,
ZEND_ACC_PUBLIC ZEND_ACC_PRIVATE ZEND_ACC_PROTECTED是我们类里面的三个访问权限
ZEND_ACC_CTOR标示构造函数
ZEND_ACC_DTOR标示析构函数
4.修改PHP_MINIT_FUNCTION
前面我们说过 PHP_MINIT_FUNCTION是在模块启动的时候执行的函数
首先创建一个全局指针 zend_class_entry *person_ce;
在PHP_MINIT_FUNCTION加入如下代码
|
1
2
3
4
|
zend_class_entry person;INIT_CLASS_ENTRY(person,"Person",person_functions);person_ce=zend_register_internal_class_ex(&person,NULL,NULL TSRMLS_CC);zend_declare_property_null(person_ce,ZEND_STRL("name"),ZEND_ACC_PUBLIC TSRMLS_CC); |
1行创建一个zend_class_entry对象person.
zend_class_entry这个结构体前面也讲过 PHP内核研究之类的实现
2行初始化zend_class_entry 它执行了如下代码
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
{ \ int _len = class_name_len; \ class_container.name = zend_strndup(class_name, _len); \ class_container.name_length = _len; \ class_container.builtin_functions = functions; \ class_container.constructor = NULL; \ class_container.destructor = NULL; \ class_container.clone = NULL; \ class_container.serialize = NULL; \ class_container.unserialize = NULL; \ class_container.create_object = NULL; \ class_container.interface_gets_implemented = NULL; \ class_container.get_static_method = NULL; \ class_container.__call = handle_fcall; \ class_container.__callstatic = NULL; \ class_container.__tostring = NULL; \ class_container.__get = handle_propget; \ class_container.__set = handle_propset; \ class_container.__unset = handle_propunset; \ class_container.__isset = handle_propisset; \ class_container.serialize_func = NULL; \ class_container.unserialize_func = NULL; \ class_container.serialize = NULL; \ class_container.unserialize = NULL; \ class_container.parent = NULL; \ class_container.num_interfaces = 0; \ class_container.interfaces = NULL; \ class_container.get_iterator = NULL; \ class_container.iterator_funcs.funcs = NULL; \ class_container.module = NULL; \} |
可以对应文章>> PHP内核研究之类的实现来分析
zend_declare_property_null(person_ce,ZEND_STRL(“name”),ZEND_ACC_PUBLIC TSRMLS_CC);
创建一个值为NULL的属性
第一个参数是类名,第二个参数是 属性名称,第三个参数是属性名的长度,因为ZEND_STRL宏定义了长度,所以这里不用再传递长度.
第四个参数是属性的访问权限.
还有其他几个函数用来创建不同类型的属性
|
1
2
3
4
5
6
7
|
zend_declare_property_boolzend_declare_property_doublezend_declare_property_exzend_declare_property_longzend_declare_property_nullzend_declare_property_stringzend_declare_property_stringl |
5.创建 php_siren.h头文件中的方法体
|
1
2
3
4
5
6
7
8
9
10
11
12
|
PHP_METHOD(Person,__construct){ php_printf("construct is running<br>");}PHP_METHOD(Person,__destruct){ php_printf("destruct is running<br>");}PHP_METHOD(Person,setproperty){}PHP_METHOD(Person,getproperty){} |
6.最后make&& make install
编译我们的扩展,
重新启动apache.
$p=new Person();
?>
我们就能在浏览器里看到输出的内容
construct is running
destruct is running
这样 ..我们用扩展创建的一个基本类就完成了.
[转]自己写PHP扩展之创建一个类的更多相关文章
- linq to sql用partial扩展属性,创建一个部分类(用于多表连接)
1.在窗体中创建dataGridView显示表: using System; using System.Collections.Generic; using System.ComponentModel ...
- C++ //构造函数调用规则 //1.创建一个类,C++编译器会给每个类添加至少3个函数 //默认构造(空实现) //析构函数(空实现) //拷贝函数(值拷贝) //2.如果我们写了有参构造函数 编译器就不会提供默认构造函数 但是会提供拷贝构造函数 //3.如果我们写了拷贝函数 编译器就不再提供 默认 有参 构造函数
//构造函数调用规则 #include <iostream> using namespace std; //1.创建一个类,C++编译器会给每个类添加至少3个函数 //默认构造(空实现) ...
- JS怎么创建一个类?
15. JS怎么创建一个类? 方式1 : var obj = new Object(); 方式2 : var obj = {}; 16.JS的typeof返回哪些数据类型? string.number ...
- 创建一个类Person
创建一个类Person,包含以下属性:姓名(name).年龄(age).朋友(friends数组).问候(sayhi方法,输出问候语,例如:"你好!").交朋友(addFriend ...
- idea快速创建一个类 实现一个接口
一 创建一个接口类 二 点击接口名称 按alt + ent 三 选择implement interface 选项 完美!!!!!!!
- PHP - 创建一个类
/* * 类的实现 */ //声明一个类 class Person { //私有字段 private $name; private $sex; private $age; //构造函数 functio ...
- 用NodeJS创建一个聊天服务器
Node 是专注于创建网络应用的,网络应用就需要许多I/O(输入/输出)操作.让我们用Node实现有多么简单,并且还能轻松扩展. 创建一个TCP服务器 var net = require('net') ...
- 使用PHP来简单的创建一个RPC服务
RPC全称为Remote Procedure Call,翻译过来为"远程过程调用".主要应用于不同的系统之间的远程通信和相互调用. 比如有两个系统,一个是PHP写的,一个是JAVA ...
- 使用PHP创建一个REST API(译)
最近API在网络领域有些风靡,明确的说是REST的影响力.这实在没什么好惊讶的,因为在任何编程语言中,消费REST API都是非常的容易.构建它也非常的简单,因为本质上你不会用到任何那些已存在很久的H ...
随机推荐
- 聊一聊 JSONP
JSONP 说到 JSONP 就要说到同源策略(Same Origin Policy), 同源策略是浏览器最核心的也是最基本的安全功能. 浏览器的同源策略,限制了来自不同源的 “document” 或 ...
- 常用str函数
echo stripslashes("Who\'s Bill Gates?"),'<br />';//去掉反斜杠 echo strtolower("AABbb ...
- spring静态代理
一.代理概念 为某个对象提供一个代理,以控制对这个对象的访问. 代理类和委托类有共同的父类或父接口,这样在任何使用委托类对象的地方都可以用代理对象替代.代理类负责请求的预处理.过滤.将请求分派给委托类 ...
- svn比对
svn版本管理, 先要把你项目添加到svn版本管理中,添加完之后,文件夹就有一个绿色的勾,已经被svn进程管理了. 文件夹里面,每一层级,都有一个.svn文件夹,这个很重要,就是靠这个存放原有的文件, ...
- Swing学习笔记1-----Swing组件类的层次
1. 从结构上划分 Swing 组件类分为两种,一种是JComponent类,一种是Windows类.其中windows类包含的是一些可以独立显示的组件,而JComponent类包含的是不可以独立显 ...
- matlab环境配置
一.环境变量设置 AMD处理器:右键单击我的电脑 属性 — >高级 —> 环境变量 —> 系统变量 —> 新建 变量名:BLAS_VERSION,值为安装目录\atlas_At ...
- [IOS]使用了cocoapods 抱错Pods was rejected as an implicit dependency for ‘libPods.a’ because its architectures ......
Pods was rejected as an implicit dependency for ‘libPods.a’ because its architectures ‘i386’ didn’t ...
- 对象的this引用
Java中的this关键字总是指向调用该方法的对象.根据this出现位置的不同,this作为对象的默认引用有两个功能: 1.构造器中引用该构造器正在初始化的对象. 2.在方法中引用调用该方法的对象. ...
- 如何给GridView添加网格
如何给gridview的单元格加上分割线 原文链接:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2013/1227/1582.html ...
- 谢欣伦 - OpenDev原创教程 - 蓝牙设备查找类CxBthRemoteDeviceFind
这是一个精练的蓝牙设备查找类,类名.函数名和变量名均采用匈牙利命名法.小写的x代表我的姓氏首字母(谢欣伦),个人习惯而已,如有雷同,纯属巧合. CxBthRemoteDeviceFind的使用如下: ...