ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

PHP扩展名:无法使用zend_hash_update更新类字段

2019-12-01 18:34:30  阅读:336  来源: 互联网

标签:php-internals c-3 php


我想实现此类到php扩展:

class MyClass {
  protected $attrs = array();
  public function __construct($id = null) {
    $this->attrs['id'] = $id;
    $this->attrs['name'] = '';
  }
  public function __get($key) {
    if (array_key_exists($key, $this->attr)) 
      return $this->attrs[$key];
  }
  public function __set($key, $value) {
    if (array_key_exists($key, $this->attr)) 
      $this->attrs[$key] = $value;
  }
}

我已经实现了__constructor,$attrs字段和__get方法.现在我不知道__set了.

有我的C代码:

PHP_METHOD(MyClass, __set) {    
  char *key;
  int key_len;
  zval *value;  

  if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &key, &key_len, &value)) {
    RETURN_NULL();
  }

  zval *attrs, *obj;
  obj = getThis();
  attrs = zend_read_property(Z_OBJCE_P(obj), obj, "attrs", strlen("attrs"), TRUE, TSRMLS_C);

  if (Z_TYPE_P(attrs) == IS_ARRAY && zend_hash_exists(Z_ARRVAL_P(attrs), key, strlen(key) + 1)) {
    zend_hash_update(Z_ARRVAL_P(attributes), key, strlen(key) + 1, &value, sizeof(zval*), NULL);
    }
  else {        
    zend_throw_exception_ex(zend_exception_get_default(TSRMLS_C), 1, TSRMLS_C, "unknown field \"%s\"", key);
  }
}

attrs-初始化函数中声明的受保护属性(我将属性声明为null,但是当我向构造函数中的$attrs添加数据时-属性更新为数组)

zend_declare_property_null(myclass_ce, "attrs", strlen("attrs"), ZEND_ACC_PROTECTED TSRMLS_CC);

所以我的问题是:我该如何在c中更新attr字段?
我的扩展成功编译,我可以定义属性,读取它们,但不能设置它们-因为设置的值变为null,例如:

class MyClass2 extends MyClass {
  public function __construct($id = null) {
    parent::__construct($id);
    $this->attrs["type"] = "clz";
  }
} 

$c = new MyClass();
var_dump($c->type); // string(3) "clz"
$c->type = "myclz"; // no error, my __set method handles this call, and I'm sure I'm getting correct value 
var_dump($c->type); // NULL

我是c开发的新手,我真的需要帮助.

UPD 1.我尝试将__set主体更改为此:

zval *strval;
MAKE_STD_ZVAL(strval);
ZVAL_STRING(strval, Z_STRVAL_P(value), TRUE);
if (Z_TYPE_P(attributes) == IS_ARRAY && zend_hash_exists(Z_ARRVAL_P(attributes), key, strlen(key) + 1)) {
  zend_hash_update(HASH_OF(attributes), key, strlen(key) + 1, &strval, sizeof(zval*), NULL);
}

现在,我可以设置字符串值了.如果我需要打开每种类型的zval?

解决方法:

这应该工作:

PHP_METHOD(MyClass, __set) {    
  char *key;
  int key_len;
  zval *value, *copied;  

  if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &key, &key_len, &value)) {
    RETURN_NULL();
  }

  zval *attrs, *obj;
  obj = getThis();
  attrs = zend_read_property(Z_OBJCE_P(obj), obj, "attrs", strlen("attrs"), TRUE, TSRMLS_C);

  MAKE_STD_ZVAL(copied);
  *copied = *value;
  zval_copy_ctor(copied);

  if (Z_TYPE_P(attrs) == IS_ARRAY && zend_hash_exists(Z_ARRVAL_P(attrs), key, strlen(key) + 1)) {
    zend_hash_update(Z_ARRVAL_P(attributes), key, strlen(key) + 1, &copied, sizeof(zval*), NULL);
  }
  else {        
    zend_throw_exception_ex(zend_exception_get_default(TSRMLS_C), 1, TSRMLS_C, "unknown field \"%s\"", key);
  }
}

标签:php-internals,c-3,php
来源: https://codeday.me/bug/20191201/2082575.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有