summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/value.h1
-rw-r--r--zend/callable.cpp17
-rw-r--r--zend/callable.h13
-rw-r--r--zend/objectimpl.h25
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;
}
/**