summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2014-06-11 10:45:01 +0200
committerEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2014-06-11 10:45:01 +0200
commitb4936cbc31c20c390d50333da5c83ff31795acf7 (patch)
tree8e25fef14825b2be5f493249ab401b0bbc05f70d
parent9502a731c09593db0d3b7ad3a1d3ee90b8b44901 (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.h4
-rw-r--r--zend/classimpl.cpp56
-rw-r--r--zend/classimpl.h19
-rw-r--r--zend/object.cpp5
-rw-r--r--zend/objectimpl.h2
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