diff options
author | Emiel Bruijntjes <emiel.bruijntjes@copernica.com> | 2014-03-14 10:32:32 +0100 |
---|---|---|
committer | Emiel Bruijntjes <emiel.bruijntjes@copernica.com> | 2014-03-14 10:32:32 +0100 |
commit | 4c55148476952276ece19f5b975ca0a0233dee4c (patch) | |
tree | f16b9da14403c33f1ca951e16e58841a3d88f091 | |
parent | 159781ee8257329ca9c40306f7495a8c2f31f710 (diff) |
implemented __destruct magic method
-rw-r--r-- | include/base.h | 5 | ||||
-rw-r--r-- | include/class.h | 15 | ||||
-rw-r--r-- | include/classbase.h | 13 | ||||
-rw-r--r-- | src/base.cpp | 35 | ||||
-rw-r--r-- | src/classbase.cpp | 47 |
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 |