summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/base.h5
-rw-r--r--include/class.h15
-rw-r--r--include/classbase.h13
-rw-r--r--src/base.cpp35
-rw-r--r--src/classbase.cpp47
5 files changed, 90 insertions, 25 deletions
diff --git a/include/base.h b/include/base.h
index 6cf75df..2d5b815 100644
--- a/include/base.h
+++ b/include/base.h
@@ -111,6 +111,11 @@ public:
{
return Value(this)[name];
}
+
+ /**
+ * Overridable method that is called right before an object is destructed
+ */
+ void __destruct() const;
/**
* Overridable method that is called to check if a property is set
diff --git a/include/class.h b/include/class.h
index 9fa14a7..31e29a8 100644
--- a/include/class.h
+++ b/include/class.h
@@ -247,7 +247,7 @@ private:
T *object = (T *)base;
// call the method on the base object
- return base->__call(name, params);
+ return object->__call(name, params);
}
/**
@@ -302,6 +302,19 @@ private:
}
/**
+ * Call the __destruct method
+ * @param object
+ */
+ virtual Value callDestruct(Base *base) const override
+ {
+ // cast to actual object
+ T *obj = (T *)base;
+
+ // pass on
+ return obj->__destruct();
+ }
+
+ /**
* Call a the __callStatic() function
* @param name Name of the function
* @param params Parameters passed to the function
diff --git a/include/classbase.h b/include/classbase.h
index 0ea6ea4..24e8f5a 100644
--- a/include/classbase.h
+++ b/include/classbase.h
@@ -150,6 +150,11 @@ protected:
virtual int callCompare(Base *object1, Base *object2) const { return 1; }
/**
+ * Call the __destruct method
+ */
+ virtual Value callDestruct(Base *base) const { return nullptr; }
+
+ /**
* Call the __call(), __invoke() or __callStatic() method
* @param base Object to call on
* @param name Name of the method
@@ -283,6 +288,8 @@ private:
*/
static struct _zend_object_value createObject(struct _zend_class_entry *entry);
static struct _zend_object_value cloneObject(struct _zval_struct *val);
+ static void destructObject(struct _zend_object *object, unsigned int handle);
+ static void freeObject(struct _zend_object *object);
/**
* Static member function that get called when a method or object is called
@@ -495,6 +502,12 @@ private:
* @var std::list
*/
std::list<std::shared_ptr<Member>> _members;
+
+ /**
+ * Base object has access to the members
+ * This is needed by the Base::store() method
+ */
+ friend class Base;
};
/**
diff --git a/src/base.cpp b/src/base.cpp
index 2c46147..f677bcf 100644
--- a/src/base.cpp
+++ b/src/base.cpp
@@ -13,29 +13,6 @@
namespace Php {
/**
- * Function that is called to clean up space that is occupied by the object
- * @param object The object to be deallocated
- */
-static void deallocate_object(void *object TSRMLS_DC)
-{
- // allocate memory for the object
- MixedObject *obj = (MixedObject *)object;
-
- // deallocate the cpp object
- if (obj->cpp) delete obj->cpp;
-
- // get rid of the object properties
- // @todo if we enable the following two lines, segmentation
- // faults and memory corruption occurs. however, the online
- // documentation does it like this
- //zend_hash_destroy(obj->php.properties);
- //FREE_HASHTABLE(obj->php.properties);
-
- // deallocate the entire object
- efree(obj);
-}
-
-/**
* Store the object in the PHP object cache
* @param entry Class entry
* @return MixedObject
@@ -71,13 +48,23 @@ MixedObject *Base::store(zend_class_entry *entry)
// 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(result, NULL, deallocate_object, NULL TSRMLS_CC);
+ _handle = zend_objects_store_put(result, (zend_objects_store_dtor_t)ClassBase::destructObject, (zend_objects_free_object_storage_t)ClassBase::freeObject, NULL TSRMLS_CC);
// done
return result;
}
/**
+ * Overridable method that is called right before an object is destructed
+ */
+void Base::__destruct() const
+{
+ // throw exception, so that the PHP-CPP library will check if the user
+ // somehow registered an explicit __destruct method
+ throw NotImplemented();
+}
+
+/**
* Overridable method that is called to check if a property is set
*
* The default implementation does nothing, and the script will fall back
diff --git a/src/classbase.cpp b/src/classbase.cpp
index ec316cd..2fae658 100644
--- a/src/classbase.cpp
+++ b/src/classbase.cpp
@@ -1077,6 +1077,53 @@ void ClassBase::unsetProperty(zval *object, zval *member, const struct _zend_lit
}
/**
+ * Function that is called when an object is about to be destructed
+ * This will call the magic __destruct method
+ */
+void ClassBase::destructObject(zend_object *object, zend_object_handle handle)
+{
+ // allocate memory for the object
+ MixedObject *obj = (MixedObject *)object;
+
+ // get meta info
+ ClassBase *meta = cpp_class(object->ce);
+
+ // prevent exceptions
+ try
+ {
+ // call the destruct function
+ if (obj->cpp) meta->callDestruct(obj->cpp);
+ }
+ catch (const NotImplemented &exception)
+ {
+ // fallback on the default destructor call
+ zend_objects_destroy_object(object, handle);
+ }
+ catch (Exception &exception)
+ {
+ // a regular Php::Exception was thrown by the extension, pass it on
+ // to PHP user space
+ exception.process();
+ }
+}
+
+/**
+ * Function that is called to clean up space that is occupied by the object
+ * @param object The object to be deallocated
+ */
+void ClassBase::freeObject(zend_object *object)
+{
+ // allocate memory for the object
+ MixedObject *obj = (MixedObject *)object;
+
+ // deallocate the cpp object
+ if (obj->cpp) delete obj->cpp;
+
+ // pass on to the default destructor
+ zend_objects_free_object_storage(object);
+}
+
+/**
* Function that is called when an instance of the class needs to be created.
* This function will create the C++ class, and the PHP object
* @param entry Pointer to the class information