Как правильно получить экземпляр объекта внутри его собственного метода в формате zval и обновить свойство с длинным значением?

#php #c

#php #c

Вопрос:

Я создаю расширение для php на c, но у меня возникла ошибка при обновлении свойства типа long. Я пытаюсь использовать приведенный ниже код для обновления свойства.

 zend_update_property_long(kaya_class_entry, getThis(), "lastError", sizeof("lastError") - 1, error);  

Это моя реализация метода, который использует «getThis()» везде, где я использую «getThis ()», выдает ошибку.

 PHP_METHOD (Kaya, login) {   KAYA *ptr = NULL;  zend_string * username;  zend_string * password;  ZEND_PARSE_PARAMETERS_START(2, 2)  Z_PARAM_STR(username)  Z_PARAM_STR(password)  ZEND_PARSE_PARAMETERS_END();  zend_resource *kaya;  zval kaya_ptr;  int error;   char *mUsername = ZSTR_VAL(username);  char *mPassword = ZSTR_VAL(password);   char *mLicenseDir = licenseDir();  ptr = fn_kaya_login(mLicenseDir, mUsername, mPassword, amp;error);  if (mLicenseDir != NULL) free(mLicenseDir);   zend_update_property_long(kaya_class_entry, getThis(), "lastError", sizeof("lastError") - 1, error);  if (ptr == NULL) RETURN_FALSE;   kaya = zend_register_resource((void *) ptr, le_kaya);  ZVAL_RES(amp;kaya_ptr, kaya);  zend_update_property(kaya_class_entry, getThis(), "resource", sizeof("resource") - 1, amp;kaya_ptr TSRMLS_CC);  RETURN_TRUE; }  

При компиляции я получаю следующую ошибку.

 In file included from /usr/include/php/20210902/main/php.h:36,  from /tmp/tmp.b71QT2xy5G/ext/kaya.c:7: /tmp/tmp.b71QT2xy5G/ext/kaya.c: In function 'zim_Kaya_login': /usr/include/php/20210902/Zend/zend_API.h:472:73: warning: passing argument 2 of 'zend_update_property_long' from incompatible pointer type [-Wincompatible-pointer-types]  #define getThis() ((Z_TYPE_P(ZEND_THIS) == IS_OBJECT) ? ZEND_THIS : NULL)  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~ /tmp/tmp.b71QT2xy5G/ext/kaya.c:138:49: note: in expansion of macro 'getThis'  zend_update_property_long(kaya_class_entry, getThis(), "lastError", sizeof("lastError") - 1, error);  ^~~~~~~ /usr/include/php/20210902/Zend/zend_API.h:446:79: note: expected 'zend_object *' {aka 'struct _zend_object *'} but argument is of type 'zval *' {aka 'struct _zval_struct *'}  oid zend_update_property_long(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, zend_long value);  ~~~~~~~~~~~~~^~~~~~  

Ответ №1:

В php 5 вы можете сделать это так

 custom_object *obj = (custom_object *)zend_object_store_get_object(  getThis() TSRMLS_CC);  

[ПРАВИТЬ] Для php 7 вы можете сделать это так

 zend_object *obj = Z_OBJ_P(getThis());  

К сожалению, я также застрял на этом для php 7, и я провожу исследования около 5-6 часов, они изменили много команд и функций для php7, поэтому я думаю, что это стало невозможным. Если это возможно, то я действительно потрясен тем, насколько плохо задокументирован этот материал, даже здесь, на StackOverflow, это первая тема об этом за 5 лет. Даже их официальные «документы» больше не актуальны.

Комментарии:

1. Я создал макрос: #определите ЭТОТ_КАЯ_ОБЪЕКТ() (zend_object*)Z_OBJ_P(getThis()) и удалите все ссылки из ZTS (TSRMLS_CC, TSRMLS_C и другие) возможно использовать #определить, чтобы не удалять, и есть разница, когда включить поддержку cpp PHP_REQUIRE_CXX теперь мой код работает.

Ответ №2:

Возможным способом решения этой проблемы было бы:

Вы можете бросить:

 (zend_object *) Z_OBJ_P (getThis())  

Или создайте макрос, используя приведение

 #define GET_INSTANCE() (zend_object *) Z_OBJ_P (getThis())   

и удалите «TSRMLS_CC», TSRMLS_CC-это макрос, который используется, когда включена функция ZTS

 zend_object *object = GET_INSTANCE(); zend_update_property(kaya_class_entry, object, "resource", sizeof("resource") - 1, amp;kaya_ptr);