php 内置接口,php扩展实践之implements内置接口

这次用 php 扩展的方式来实现一下 Laravel5.1 Support 中的 Fluent,实现一下 php 内置接口 ArrayAccess 的方法

method参数的定义#include "Zend/zend_interfaces.h"

zend_class_entry *fluent_ce;

ZEND_BEGIN_ARG_INFO_EX(arginfo_fluent___construct, 0, 0, 1)

ZEND_ARG_ARRAY_INFO(0, attributes, 0)

ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO_EX(arginfo_fluent_offsetexists, 0, 0, 1)

ZEND_ARG_INFO(0, offset)

ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO_EX(arginfo_fluent_offsetget, 0, 0, 1)

ZEND_ARG_INFO(0, offset)

ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO_EX(arginfo_fluent_offsetset, 0, 0, 2)

ZEND_ARG_INFO(0, offset)

ZEND_ARG_INFO(0, value)

ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO_EX(arginfo_fluent_offsetunset, 0, 0, 1)

ZEND_ARG_INFO(0, offset)

ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO_EX(arginfo_fluent___get, 0, 0, 1)

ZEND_ARG_INFO(0, name)

ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO_EX(arginfo_fluent___set, 0, 0, 2)

ZEND_ARG_INFO(0, name)

ZEND_ARG_INFO(0, value)

ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO_EX(arginfo_fluent___isset, 0, 0, 1)

ZEND_ARG_INFO(0, name)

ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO_EX(arginfo_fluent___unset, 0, 0, 1)

ZEND_ARG_INFO(0, name)

ZEND_END_ARG_INFO()

定义类方法ZEND_METHOD(fluent, __construct) {

zval *attributes, *instance;

MAKE_STD_ZVAL(attributes);

array_init(attributes);

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a", &attributes) == FAILURE) {

RETURN_NULL();

}

instance = getThis();

zend_update_property(fluent_ce, instance, ZEND_STRL("attributes"), attributes TSRMLS_DC);

}

ZEND_METHOD(fluent, offsetExists) {

zval *value, *instance, *member;

char *offset;

int offsetLen;

int exists;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &offset, &offsetLen) == FAILURE) {

RETURN_NULL();

}

instance = getThis();

MAKE_STD_ZVAL(member);

ZVAL_STRINGL(member, offset, offsetLen, 1);

exists = std_object_handlers.has_property(instance, member, 0, 0 TSRMLS_DC);

zval_ptr_dtor(&member);

RETURN_BOOL(exists);

}

ZEND_METHOD(fluent, offsetGet) {

zval *value, *instance;

char *offset;

int offsetLen;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &offset, &offsetLen) == FAILURE) {

RETURN_NULL();

}

instance = getThis();

php_printf("%s\n", offset);

value = zend_read_property(fluent_ce, instance, offset, offsetLen, 1 TSRMLS_CC);

RETURN_ZVAL(value, 1, 0);

}

ZEND_METHOD(fluent, offsetSet) {

zval *value, *instance;

char *offset;

int offsetLen;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &offset, &offsetLen, &value) == FAILURE) {

RETURN_NULL();

}

instance = getThis();

zend_update_property(fluent_ce, instance, offset, offsetLen, value TSRMLS_DC);

}

ZEND_METHOD(fluent, offsetUnset) {

zval *instance, *member;

char *offset;

int offsetLen;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &offset, &offsetLen) == FAILURE) {

RETURN_NULL();

}

instance = getThis();

MAKE_STD_ZVAL(member);

ZVAL_STRINGL(member, offset, offsetLen, 1);

std_object_handlers.unset_property(instance, member, 0 TSRMLS_DC);

zval_ptr_dtor(&member);

}

ZEND_METHOD(fluent, __get) {

char *name;

int nameLen;

zval *attributes, *instance;

zval **value;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &nameLen) == FAILURE) {

RETURN_NULL();

}

instance = getThis();

attributes = zend_read_property(fluent_ce, instance, ZEND_STRL("attributes"), 0 TSRMLS_CC);

if (zend_hash_find(Z_ARRVAL_P(attributes), name, nameLen + 1, (void **)&value) == SUCCESS) {

RETURN_ZVAL(*value, 1, 0);

} else {

RETURN_NULL();

}

}

ZEND_METHOD(fluent, __set) {

char *name;

int nameLen;

zval *value, *attributes, *instance;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &name, &nameLen, &value) == FAILURE) {

RETURN_NULL();

}

instance = getThis();

attributes = zend_read_property(fluent_ce, instance, ZEND_STRL("attributes"), 0 TSRMLS_CC);

add_assoc_zval(attributes, name, value);

zval_add_ref(&value);

}

ZEND_METHOD(fluent, __isset) {

char *name;

int nameLen;

zval *attributes, *instance;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &nameLen) == FAILURE) {

RETURN_NULL();

}

instance = getThis();

attributes = zend_read_property(fluent_ce, instance, ZEND_STRL("attributes"), 0 TSRMLS_CC);

if (zend_hash_exists(Z_ARRVAL_P(attributes), name, nameLen + 1) == SUCCESS) {

RETURN_BOOL(1);

} else {

RETURN_BOOL(0);

}

}

ZEND_METHOD(fluent, __unset) {

char *name;

int nameLen;

zval *attributes, *instance;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &nameLen) == FAILURE) {

RETURN_NULL();

}

instance = getThis();

attributes = zend_read_property(fluent_ce, instance, ZEND_STRL("attributes"), 0 TSRMLS_CC);

zend_hash_del(Z_ARRVAL_P(attributes), name, nameLen + 1);

}

static zend_function_entry fluent_methods[] = {

ZEND_ME(fluent, __construct, arginfo_fluent___construct, ZEND_ACC_CTOR | ZEND_ACC_PUBLIC)

ZEND_ME(fluent, offsetExists, arginfo_fluent_offsetexists, ZEND_ACC_PUBLIC)

ZEND_ME(fluent, offsetGet, arginfo_fluent_offsetget, ZEND_ACC_PUBLIC)

ZEND_ME(fluent, offsetSet, arginfo_fluent_offsetset, ZEND_ACC_PUBLIC)

ZEND_ME(fluent, offsetUnset, arginfo_fluent_offsetunset, ZEND_ACC_PUBLIC)

ZEND_ME(fluent, __get, arginfo_fluent___get, ZEND_ACC_PUBLIC)

ZEND_ME(fluent, __set, arginfo_fluent___set, ZEND_ACC_PUBLIC)

ZEND_ME(fluent, __isset, arginfo_fluent___isset, ZEND_ACC_PUBLIC)

ZEND_ME(fluent, __unset, arginfo_fluent___unset, ZEND_ACC_PUBLIC)

{NULL, NULL, NULL}

};

模块初始化的时候注册类PHP_MINIT_FUNCTION(learn)

{

zval *attributes;

MAKE_STD_ZVAL(attributes);

array_init(attributes);

zend_class_entry ce;

INIT_CLASS_ENTRY(ce, "Fluent", fluent_methods);

fluent_ce = zend_register_internal_class(&ce TSRMLS_CC);

// implements ArrayAccess

zend_class_implements(fluent_ce TSRMLS_DC, 1, zend_ce_arrayaccess);

zend_declare_property_null(fluent_ce, ZEND_STRL("attributes"), ZEND_ACC_PROTECTED TSRMLS_CC);

return SUCCESS;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值