diff options
-rw-r--r-- | include/value.h | 1 | ||||
-rw-r--r-- | zend/callable.cpp | 17 | ||||
-rw-r--r-- | zend/callable.h | 13 | ||||
-rw-r--r-- | zend/objectimpl.h | 25 |
4 files changed, 39 insertions, 17 deletions
diff --git a/include/value.h b/include/value.h index 844f978..95985d7 100644 --- a/include/value.h +++ b/include/value.h @@ -949,6 +949,7 @@ protected: friend class TraverseIterator; friend class HashMember<int>; friend class HashMember<std::string>; + friend class Callable; }; /** diff --git a/zend/callable.cpp b/zend/callable.cpp index 737b85b..96f5f90 100644 --- a/zend/callable.cpp +++ b/zend/callable.cpp @@ -23,7 +23,7 @@ namespace Php { * @param tsrm_ls * @return integer */ -static void invoke_callable(INTERNAL_FUNCTION_PARAMETERS) +void Callable::invoke(INTERNAL_FUNCTION_PARAMETERS) { // find the function name const char *name = get_active_function_name(TSRMLS_C); @@ -31,9 +31,6 @@ static void invoke_callable(INTERNAL_FUNCTION_PARAMETERS) // uncover the hidden pointer inside the function name Callable *callable = HiddenPointer<Callable>(name); - // wrap the return value - Value result(return_value, true); - // construct parameters ParametersImpl params(this_ptr, ZEND_NUM_ARGS() TSRMLS_CC); @@ -41,7 +38,15 @@ static void invoke_callable(INTERNAL_FUNCTION_PARAMETERS) try { // get the result - result = callable->invoke(params); + Value result(callable->invoke(params)); + + // detach the zval (we don't want it to be destructed) + zval *val = result.detach(); + + // @todo php 5.6 has a RETVAL_ZVAL_FAST macro that can be used instead (and is faster) + + // return a full copy of the zval, and do not destruct it + RETVAL_ZVAL(val, 1, 0); } catch (Exception &exception) { @@ -64,7 +69,7 @@ void Callable::initialize(zend_function_entry *entry, const char *classname, int { // fill the members of the entity, and hide a pointer to the current object in the name entry->fname = (const char *)_ptr; - entry->handler = invoke_callable; + entry->handler = &Callable::invoke; entry->arg_info = _argv; entry->num_args = _argc; entry->flags = flags; diff --git a/zend/callable.h b/zend/callable.h index 9805174..67863a9 100644 --- a/zend/callable.h +++ b/zend/callable.h @@ -181,6 +181,19 @@ protected: info->allow_null = arg.allowNull(); info->pass_by_reference = arg.byReference(); } + + /** + * Function that is called by the Zend engine every time that a function gets called + * @param ht + * @param return_value + * @param return_value_ptr + * @param this_ptr + * @param return_value_used + * @param tsrm_ls + * @return integer + */ + static void invoke(INTERNAL_FUNCTION_PARAMETERS); + }; /** diff --git a/zend/objectimpl.h b/zend/objectimpl.h index 41bed53..f66a6ab 100644 --- a/zend/objectimpl.h +++ b/zend/objectimpl.h @@ -20,7 +20,7 @@ class ObjectImpl { private: /** - * Structure with a first element which is a mixed object, so that + * Structure with a first element which is a zend_object, so that * it can be casted to a zend_object * @var MixedObject */ @@ -40,7 +40,7 @@ private: ObjectImpl *self; - } _mixed; + } *_mixed; /** * Pointer to the C++ implementation @@ -66,15 +66,18 @@ public: */ ObjectImpl(zend_class_entry *entry, Base *base TSRMLS_DC) { + // allocate a mixed object (for some reason this does not have to deallocated) + _mixed = (MixedObject *)emalloc(sizeof(MixedObject)); + // copy properties to the mixed object - _mixed.php.ce = entry; - _mixed.self = this; + _mixed->php.ce = entry; + _mixed->self = this; // store the c++ object _object = base; // initialize the object - zend_object_std_init(&_mixed.php, entry TSRMLS_CC); + zend_object_std_init(&_mixed->php, entry TSRMLS_CC); #if PHP_VERSION_ID < 50399 @@ -82,12 +85,12 @@ public: zval *tmp; // initialize the properties, php 5.3 way - zend_hash_copy(_mixed.php.properties, &entry->default_properties, (copy_ctor_func_t) zval_property_ctor, &tmp, sizeof(zval*)); + zend_hash_copy(_mixed->php.properties, &entry->default_properties, (copy_ctor_func_t) zval_property_ctor, &tmp, sizeof(zval*)); #else // version higher than 5.3 have an easier way to initialize - object_properties_init(&_mixed.php, entry); + object_properties_init(&_mixed->php, entry); #endif @@ -112,7 +115,7 @@ public: // the destructor and clone handlers are set to NULL. I dont know why, but they do not // seem to be necessary... - _handle = zend_objects_store_put(&_mixed, (zend_objects_store_dtor_t)destructMethod, (zend_objects_free_object_storage_t)freeMethod, NULL TSRMLS_CC); + _handle = zend_objects_store_put(php(), (zend_objects_store_dtor_t)destructMethod, (zend_objects_free_object_storage_t)freeMethod, NULL TSRMLS_CC); // the object may remember that we are its implementation object base->_impl = this; @@ -124,7 +127,7 @@ public: virtual ~ObjectImpl() { // deallocate the cpp object - delete _object; + if (_object) delete _object; } /** @@ -134,7 +137,7 @@ public: void destruct(TSRMLS_D) { // pass on to the default destructor - zend_objects_free_object_storage(&_mixed.php TSRMLS_CC); + zend_objects_free_object_storage(php() TSRMLS_CC); // destruct the object delete this; @@ -184,7 +187,7 @@ public: */ zend_object *php() { - return &_mixed.php; + return &_mixed->php; } /** |