diff options
author | Emiel Bruijntjes <emiel.bruijntjes@copernica.com> | 2014-06-11 10:45:01 +0200 |
---|---|---|
committer | Emiel Bruijntjes <emiel.bruijntjes@copernica.com> | 2014-06-11 10:45:01 +0200 |
commit | b4936cbc31c20c390d50333da5c83ff31795acf7 (patch) | |
tree | 8e25fef14825b2be5f493249ab401b0bbc05f70d | |
parent | 9502a731c09593db0d3b7ad3a1d3ee90b8b44901 (diff) |
when an object was created using Php::Object("MyClass", new MyClass()), the object handlers were not installed, which caused the magic methods not to be functional (issue #94)
-rw-r--r-- | include/classbase.h | 4 | ||||
-rw-r--r-- | zend/classimpl.cpp | 56 | ||||
-rw-r--r-- | zend/classimpl.h | 19 | ||||
-rw-r--r-- | zend/object.cpp | 5 | ||||
-rw-r--r-- | zend/objectimpl.h | 2 |
5 files changed, 56 insertions, 30 deletions
diff --git a/include/classbase.h b/include/classbase.h index a736c4e..9f0bac3 100644 --- a/include/classbase.h +++ b/include/classbase.h @@ -2,9 +2,9 @@ * ClassBase.h * * This is the base class of the "Class" class. This is an internal class that - * is used by the PHP-CPP library. But because the constructor is protected, + * is used by the PHP-CPP library. Because the constructor is protected, * you can not create any instances if this class yourself (and you are not - * supposed to do that either. + * supposed to do that either). * * Further more, because this base class is a 'private' base of Class, all * features of it are normally also inaccessible. diff --git a/zend/classimpl.cpp b/zend/classimpl.cpp index d63956a..953738a 100644 --- a/zend/classimpl.cpp +++ b/zend/classimpl.cpp @@ -330,52 +330,56 @@ int ClassImpl::getClosure(zval *object, zend_class_entry **entry_ptr, zend_funct */ zend_object_handlers *ClassImpl::objectHandlers() { - // keep static structure - static zend_object_handlers handlers; - - // is the object already initialized? - static bool initialized = false; - // already initialized? - if (initialized) return &handlers; + if (_initialized) return &_handlers; // initialize the handlers - memcpy(&handlers, &std_object_handlers, sizeof(zend_object_handlers)); + memcpy(&_handlers, &std_object_handlers, sizeof(zend_object_handlers)); // install custom clone function - if (!_base->clonable()) handlers.clone_obj = nullptr; - else handlers.clone_obj = &ClassImpl::cloneObject; + if (!_base->clonable()) _handlers.clone_obj = nullptr; + else _handlers.clone_obj = &ClassImpl::cloneObject; // functions for the Countable interface - handlers.count_elements = &ClassImpl::countElements; + _handlers.count_elements = &ClassImpl::countElements; // functions for the ArrayAccess interface - handlers.write_dimension = &ClassImpl::writeDimension; - handlers.read_dimension = &ClassImpl::readDimension; - handlers.has_dimension = &ClassImpl::hasDimension; - handlers.unset_dimension = &ClassImpl::unsetDimension; + _handlers.write_dimension = &ClassImpl::writeDimension; + _handlers.read_dimension = &ClassImpl::readDimension; + _handlers.has_dimension = &ClassImpl::hasDimension; + _handlers.unset_dimension = &ClassImpl::unsetDimension; // functions for the magic properties handlers (__get, __set, __isset and __unset) - handlers.write_property = &ClassImpl::writeProperty; - handlers.read_property = &ClassImpl::readProperty; - handlers.has_property = &ClassImpl::hasProperty; - handlers.unset_property = &ClassImpl::unsetProperty; + _handlers.write_property = &ClassImpl::writeProperty; + _handlers.read_property = &ClassImpl::readProperty; + _handlers.has_property = &ClassImpl::hasProperty; + _handlers.unset_property = &ClassImpl::unsetProperty; // when a method is called (__call and __invoke) - handlers.get_method = &ClassImpl::getMethod; - handlers.get_closure = &ClassImpl::getClosure; + _handlers.get_method = &ClassImpl::getMethod; + _handlers.get_closure = &ClassImpl::getClosure; // handler to cast to a different type - handlers.cast_object = &ClassImpl::cast; + _handlers.cast_object = &ClassImpl::cast; // method to compare two objects - handlers.compare_objects = &ClassImpl::compare; + _handlers.compare_objects = &ClassImpl::compare; // remember that object is now initialized - initialized = true; + _initialized = true; // done - return &handlers; + return &_handlers; +} + +/** + * Alternative way to retrieve object handlers, given a class entry + * @param entry + * @return zend_object_handlers + */ +zend_object_handlers *ClassImpl::objectHandlers(zend_class_entry *entry) +{ + return self(entry)->objectHandlers(); } /** @@ -465,7 +469,7 @@ int ClassImpl::cast(zval *val, zval *retval, int type TSRMLS_DC) case Type::Float: result = meta->callToFloat(object).detach(); break; case Type::Bool: result = meta->callToBool(object).detach(); break; case Type::String: result = meta->callToString(object).detach(); break; - default: throw NotImplemented(); break; + default: throw NotImplemented(); break; } // @todo do we turn into endless conversion if the __toString object returns 'this' ?? diff --git a/zend/classimpl.h b/zend/classimpl.h index ec28322..bd631b8 100644 --- a/zend/classimpl.h +++ b/zend/classimpl.h @@ -84,6 +84,18 @@ private: * @var std::shared_ptr */ std::shared_ptr<ClassImpl> _parent; + + /** + * The object handlers for instances of this class + * @var zend_object_handlers + */ + zend_object_handlers _handlers; + + /** + * Are the handlers already initialized? + * @var bool + */ + bool _initialized = false; /** @@ -204,6 +216,13 @@ public: zend_object_handlers *objectHandlers(); /** + * Alternative way to retrieve object handlers, given a class entry + * @param entry + * @return zend_object_handlers + */ + static zend_object_handlers *objectHandlers(zend_class_entry *entry); + + /** * Function to create a new iterator to iterate over an object * @param entry The class entry * @param object The object to iterate over diff --git a/zend/object.cpp b/zend/object.cpp index 08553b5..940b143 100644 --- a/zend/object.cpp +++ b/zend/object.cpp @@ -22,7 +22,7 @@ Object::Object(const char *name, Base *base) // does the object already have a handle? if (base->implementation()) { - // the object is already instantiated, we can assign it the this object + // the object is already instantiated, we can assign it to this object operator=(Value(base)); } else @@ -42,6 +42,9 @@ Object::Object(const char *name, Base *base) // now we can store it operator=(Value(base)); + + // install the object handlers + Z_OBJVAL_P(_val).handlers = ClassImpl::objectHandlers(entry); } } diff --git a/zend/objectimpl.h b/zend/objectimpl.h index f66a6ab..7f16320 100644 --- a/zend/objectimpl.h +++ b/zend/objectimpl.h @@ -66,7 +66,7 @@ public: */ ObjectImpl(zend_class_entry *entry, Base *base TSRMLS_DC) { - // allocate a mixed object (for some reason this does not have to deallocated) + // allocate a mixed object (for some reason this does not have to be deallocated) _mixed = (MixedObject *)emalloc(sizeof(MixedObject)); // copy properties to the mixed object |