接着上一篇文章,本文开始在扩展内实现类的定义和对象操作。基于PHP-X提供的封装,使用C++语言可以轻松地实现一个PHP的类,还可以在C++代码中创建任意PHP对象,调用对象方法、读写对象的属性。
0x00 定义 PHP 类
底层Zend API有一个限制,定义函数必须在模块初始化之前,定义类必须在模块初始化之后。因此定义类,需要在Extension的onStart回调中进行。
-
new Class表示创建一个新的PHP类,参数为类的名称 - 调用
Class对象的addMethod来添加方法,其中PHPX_ME(CppClass, test2),这里PHPX_ME是一个宏,展开是方法的名称和函数指针,第二个参数是方法的修饰符,可以是STATIC、PROTECTED、ABSTRACT等。可以使用按位或操作符设置多个修饰符,如STATIC | PUBLIC - 调用
Class对象的addProperty添加属性 - 调用
Class对象的addConstant添加类常量
PHPX_EXTENSION()
{
Extension *ext = new Extension("test", "0.0.1");
ext->onStart = [ext]
{
Class *c = new Class("CppClass");
//注册构造方法
c->addMethod(PHPX_ME(CppClass, __construct), CONSTRUCT);
//普通方法
c->addMethod(PHPX_ME(CppClass, test1));
//普通方法
c->addMethod(PHPX_ME(CppClass, test2), STATIC);
//添加默认属性
c->addProperty("age", 30);
//添加常量
c->addConstant("VERSION", "1.9.0");
//注册类
ext->registerClass(c);
};
return ext;
}
0x01 实现类方法
方法与属性、常量不同,属性、常量添加后不需要再进行额外的操作。类方法,需要编写实际的逻辑代码。
使用PHPX_METHOD(类名, 方法名)即可。注意方法实现的代码必须在addMethod之前。
与PHPX_FUNCTION函数相同,PHPX_METHOD也有args和retval两个参数,分别用于处理PHP方法调用的参数和返回值。不同的是PHPX_METHOD多了一个_this对象,相当于PHP代码中的$this。注意如果是静态方法_this为null
PHPX_METHOD(CppClass, __construct)
{
echo("%s _construct\n", _this.getClassName().c_str());
Array array;
array.append(1234);
_this.set("name", array);
}
PHPX_METHOD(CppClass, test1)
{
//读取全局变量
Variant server = global("_SERVER");
var_dump(server);
if (server.isArray())
{
Variant shell = Array(server)["SHELL"];
var_dump(shell);
}
auto name = _this.get("name");
var_dump(name);
}
0x02 读写属性
- 调用
_this.get(property_name)读取对象属性的值 - 调用
_this.set(property_name, value)设置对象属性的值
0x03 读取类常量
使用constant函数获取类常量。
auto value = constant("CppClass::VERSION");
var_dump(value); //输出 1.9.0
0x04 编译
make install
0x05 运行
$o = new CppClass();
$o->test1();
0x06 创建 PHP 对象
在PHP-X的扩展中还可以创建PHP对象,与PHP交互操作。
Object redis = php::newObject("redis");
//连接 Redis
auto ret1 = redis.exec("connect", "127.0.0.1", 6379);
//Get Key
auto ret2 = redis.exec("get", "key");
//打印字符串
echo ("value=%s\n", ret2.toCString());