用扩展开发一个PHP类
原文:http://my.oschina.net/mickelfeng/blog/122519?p=1
假设我们要用PHP扩展实 现一个类Person,它有一个private的成员变量$_name和两个public的实例方法getName()和setName(),可以用 PHP代码表示如下:
|
1
2
3
4
5
6
7
8
9
10
11
12
|
<?php class Person{ private $_name; public function getName() { return $this -> _name; } public function setName($name) { $this -> _name = $name; } } |
1. 声明方法:还使用第一篇文章里面用过的示例,首先在头文件php_fetion_echo.h里加入方法声明。
PHP_METHOD(Person, __construct);
PHP_METHOD(Person, __destruct);
PHP_METHOD(Person, getName);
PHP_METHOD(Person, setName);
前面的扩展在声明函数时使用PHP_FUNCTION宏,而在实现类扩展时我们使用PHP_METHOD宏,第一个参数指定类名,第二个参数指定方法名。
2. 方法实现:在fetion_echo.c文件中实现这几个方法,构造函数和析构函数中只是输出一些文本。
|
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
|
PHP_METHOD(Person, __construct) { php_printf("__construct called.");}PHP_METHOD(Person, __destruct) { php_printf("__destruct called.<br/>");}PHP_METHOD(Person, getName) { zval *self, *name; self = getThis(); name = zend_read_property(Z_OBJCE_P(self), self, ZEND_STRL("_name"), 0 TSRMLS_CC); RETURN_STRING(Z_STRVAL_P(name), 0);}PHP_METHOD(Person, setName) { char *arg = NULL; int arg_len; zval *value, *self; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) == FAILURE) { WRONG_PARAM_COUNT; } self = getThis(); MAKE_STD_ZVAL(value); ZVAL_STRINGL(value, arg, arg_len, 0); SEPARATE_ZVAL_TO_MAKE_IS_REF(&value); zend_update_property(Z_OBJCE_P(self), self, ZEND_STRL("_name"), value TSRMLS_CC); RETURN_TRUE;} |
对上面的代码做一些解释:
A. 获取方法的参数信息,仍然使用zend_parse_parameters函数,与之前我们介绍过的一样;
B. 获取this指针(相对于PHP代码而言,在PHP扩展中仍然使用zval结构表示)使用getThis()函数;
C. 使用MAKE_STD_ZVAL宏申请并初始化一个zval结构,在PHP扩展中,所有的数据类型其实都是用zval结构来表示的,在本系列文章中我会单独写一篇来介绍zval。
D. 获取属性值使用zend_read_property()函数,使用zend_update_property()函数更新属性值。
3. 初始化类:在扩展初始化函数中,注册并初始化类。
zend_class_entry *person_ce; PHP_MINIT_FUNCTION(fetion_echo)
{
zend_class_entry person; INIT_CLASS_ENTRY(person, "Person", fetion_echo_functions);
person_ce = zend_register_internal_class_ex(&person, NULL, NULL TSRMLS_CC); zend_declare_property_null(person_ce, ZEND_STRL("_name"), ZEND_ACC_PRIVATE TSRMLS_CC); return SUCCESS;
}
使用INIT_CLASS_ENTRY宏初始化类,第二个参数指定类名,第三个参数是函数表。
4. 注册到函数:声明方法的参数,并注册到函数表中。
ZEND_BEGIN_ARG_INFO(arg_person_setname, 0)
ZEND_ARG_INFO(0, name)
ZEND_END_ARG_INFO() const zend_function_entry fetion_echo_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, getName, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Person, setName, arg_person_setname, ZEND_ACC_PUBLIC)
{NULL, NULL, NULL} /* Must be the last line in fetion_echo_functions[] */ };
类方法参数的声明与之前我们函数参数声明方式一致,在注册类方法到函数表中时使用PHP_ME宏,而不是之前使用的PHP_FE宏。
ZEND_ACC_PUBLIC:指定方法的访问修饰符
ZEND_ACC_CTOR:指定该方法为构造函数
ZEND_ACC_DTOR:指定该方法为析构函数
5. 运行测试:编译安装扩展后,编写一段简单的测试脚本:
<?php $person = new Person();
$person->setName("mickelfeng"); echo $person->getName().'<br/>';
运行后可以看到如下输出,说明扩展工作正常:
__construct called.
mickelfeng
__destruct called.
用扩展开发一个PHP类的更多相关文章
- 用Java开发一个工具类,提供似于js中eval函数功能的eval方法
今天在看到<Java疯狂讲义>中一个章节习题: 开发一个工具类,该工具类提供一个eval()方法,实现JavaScript中eval()函数的功能--可以动态运行一行或多行程序代码.例如: ...
- 【Android开发VR实战】三.开发一个寻宝类VR游戏TreasureHunt
转载请注明出处:http://blog.csdn.net/linglongxin24/article/details/53939303 本文出自[DylanAndroid的博客] [Android开发 ...
- php扩展开发3--扩展类传参数
1.需要实现的细节 实现一个person类 ,实现一个doing方法和saying方法 在构造方法中传递一个数组,在doing中打印此数组 saying方法中,构建一个空数组,返回,不需要传参. 2. ...
- php扩展开发2--添加类
1.需要实现的细节 实现一个person类 实现一个doing方法和saying方法 2.第一个扩展 2.1创建类的扩展: [root@bogon ext]# cd /usr/local/src/ph ...
- PHP扩展开发(4) - 多类扩展
由于函数和单类的扩展,网上一搜一大片,这里就不再叙述了. 这里特别感谢laruence(鸟哥)开源的yaf扩展,解决困扰我多时的多类问题,还在看他的代码学习中,这里是对多类写法学习的一个阶段总结. ...
- PHP扩展开发之简单类开发
接下来我们要用扩展的形式实现以下类(演示环境:linux.php-5.5.34-src) <?php class Person { private $_name; public function ...
- 行内人解读开发一个App需要多少钱?
对于很多互联网的创业者来说,评估前期的创业成本是很重要的.在这几年的创业大潮中,伴随着“互联网+”和“互联网思维”的普及,很多创业项目选择了开发app作为创业项目的载体.在我接触到的很多创业者,找Ap ...
- 如何使用Add-on SDK开发一个自己的火狐扩展
黄聪:如何使用Add-on SDK开发一个自己的火狐扩展 火狐开放了扩展的开发权限给程序员们,相信很多人都会希望自己做一些扩展来方便一些使用. 我最近做一些项目也需要开发一个火狐扩展,方便收集自己需要 ...
- 如何用原生js开发一个Chrome扩展程序
原文地址:How to Build a Simple Chrome Extension in Vanilla JavaScript 开发一个Chrome扩展程序非常简单,只需要使用原生的js就可以完成 ...
随机推荐
- Windows中使用TortoiseGit提交项目到GitLab配置
下文来给各位介绍Windows中使用TortoiseGit提交项目到GitLab配置过程,下在全部图片希望对各位带来方便面. Gitlab默认的配置推荐使用shell命令行与server端进行交互,作 ...
- linux 下使用配置文件
最近鼓捣双机热备,写了些shell脚本 适用配置文件 以 ifbeat 为例,linux的标准的配置文件中等号两遍不能存在括号, 空格 或特殊符号可以用转衣服 ' \' beat=true prima ...
- 格式化input输入内容(金额)
项目中要用到格式化金额输入框,要求每三个数字用逗号分割开. 添加一个directive angular.module('myApp.directives', []) .directive('filte ...
- DIV+CSS自适应布局
自适应布局分两类:高度和宽度,方法有很多,我用三列布局举例,我就列几个通俗易懂的例子呗,懂了三列的,两列的原理一样,呵呵哒. 效果图如下:高度自适应——宽度自适应 1,高度自适应 ...
- git学习笔记一
一.概念理解 1.理解工作区和暂存区以及版本库 工作区我理解就是我们创建的程序所在的文件夹,比如test文件夹.其中有个.git文件,这个就是版本库,其中版本库中有个区域叫暂存区或叫索引. 截自廖雪峰 ...
- [原创]MySQL RR隔离级别下begin或start transaction开启事务后的可重复读?
Server version: 5.6.21-log MySQL Community Server (GPL) 前提提要: 我们知道MySQL的RR(repeatable read)隔 ...
- ASP.NET中基本语言特性
自动属性 public string Name { get; set; } 对象与集合的初始化 //自动推断类型//集合的初始化 var Products=new List<Product> ...
- jqueryui 进度条使用
<title></title> <script src="../Js/NewJs_CFJ/jquery.js" type="text/jav ...
- GeoIP Legacy City数据库安装说明
Here is a brief outline of the steps needed to install GeoIP Legacy City on Linux/Unix. The installa ...
- Android_SQLite数据库增删改查操作
一:什么是SQLite? 在Android平台上,集成了一个嵌入式关系型轻量级的数据库. 二:什么时候用的数据库? 有大量相似机构的数据需要存储时. 三:如何创建一个数据库? 1.创建一个Sqlite ...