#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);