[Kde-bindings] playground/bindings/phpqt
Thomas Moenicke
tm at php-qt.org
Sun Sep 23 21:58:58 UTC 2007
SVN commit 716071 by moenicke:
* replaced the Zend opcode handler for 'clone', however the original one is called in it so its possible to override them in userspace
* added unittests for references and clones
CCMAIL: kde-bindings at kde.org
M +0 -1 src/context.cpp
M +28 -28 src/handlers.cpp
M +3 -0 src/marshall.h
M +2 -2 src/php_qt.cpp
M +21 -0 src/phpqt_internals.cpp
M +1 -0 src/phpqt_internals.h
M +34 -0 src/zend_handlers.cpp
M +6 -0 src/zend_handlers.h
A tests/QtAdvancedTestCase.php
--- trunk/playground/bindings/phpqt/src/context.cpp #716070:716071
@@ -93,4 +93,3 @@
{
return m_Context->m_methodNameStack.top()->constData();
}
-
--- trunk/playground/bindings/phpqt/src/handlers.cpp #716070:716071
@@ -46,14 +46,14 @@
void*
construct_copy(smokephp_object *o)
{
- const char *className;
- if(o->classId() > 0)
- {
- className = o->smoke()->className(o->classId());
- } else {
- // must be a qstring
- return o->mPtr();
- }
+ const char *className;
+ if(o->classId() > 0)
+ {
+ className = o->smoke()->className(o->classId());
+ } else {
+ // must be a qstring
+ return o->mPtr();
+ }
int classNameLen = strlen(className);
@@ -68,35 +68,35 @@
Smoke::Index ccMeth = o->smoke()->findMethod(o->classId(), ccId);
if(!ccMeth) {
- delete[] ccArg;
- return 0;
+ delete[] ccArg;
+ return 0;
}
Smoke::Index method = o->smoke()->methodMaps[ccMeth].method;
if(method > 0)
{
- // Make sure it's a copy constructor
- if(!matches_arg(o->smoke(), method, 0, ccArg)) {
- delete[] ccArg;
- return 0;
- }
- delete[] ccArg;
- ccMeth = method;
+ // Make sure it's a copy constructor
+ if(!matches_arg(o->smoke(), method, 0, ccArg)) {
+ delete[] ccArg;
+ return 0;
+ }
+ delete[] ccArg;
+ ccMeth = method;
} else {
// ambiguous method, pick the copy constructor
- Smoke::Index i = -method;
- while(o->smoke()->ambiguousMethodList[i]) {
- if(matches_arg(o->smoke(), o->smoke()->ambiguousMethodList[i], 0, ccArg))
- break;
- i++;
- }
+ Smoke::Index i = -method;
+ while(o->smoke()->ambiguousMethodList[i]) {
+ if(matches_arg(o->smoke(), o->smoke()->ambiguousMethodList[i], 0, ccArg))
+ break;
+ i++;
+ }
delete[] ccArg;
- ccMeth = o->smoke()->ambiguousMethodList[i];
- if(!ccMeth)
- {
- return 0;
- }
+ ccMeth = o->smoke()->ambiguousMethodList[i];
+ if(!ccMeth)
+ {
+ return 0;
}
+ }
// Okay, ccMeth is the copy constructor. Time to call it.
Smoke::StackItem args[2];
--- trunk/playground/bindings/phpqt/src/marshall.h #716070:716071
@@ -67,4 +67,7 @@
Marshall::HandlerFn fn;
};
+class smokephp_object;
+void* construct_copy(smokephp_object* o);
+
#endif
--- trunk/playground/bindings/phpqt/src/php_qt.cpp #716070:716071
@@ -157,7 +157,7 @@
}
ZEND_METHOD(php_qt_generic_class, __destruct)
-{
+{
if(PHPQt::SmokePHPObjectExists(getThis())) {
smokephp_object *o = PHPQt::getSmokePHPObjectFromZval(getThis());
//! its not a reference
@@ -167,7 +167,7 @@
}
if( o->allocated() )
{
- delete o->ptr();
+ delete o->ptr();
}
}
--- trunk/playground/bindings/phpqt/src/phpqt_internals.cpp #716070:716071
@@ -368,7 +368,28 @@
}
+/**
+ * create clone
+ */
+
+extern zend_class_entry* php_qt_generic_class;
+
smokephp_object*
+PHPQt::cloneObject(zval* zval_ptr, smokephp_object* so, const void* copyPtr)
+{
+ Q_ASSERT (zval_ptr);
+ Q_ASSERT (copyPtr);
+
+ smokephp_object* o = new smokephp_object(PQ::smoke(), so->classId(), copyPtr, so->ce_ptr(), zval_ptr);
+
+ Z_OBJ_HT_P(zval_ptr) = &php_qt_handler;
+ setSmokePHPObject(o);
+ o->setAllocated( true );
+ obj_x_smokephp.insert(zval_ptr->value.obj.handle, o);
+ return o;
+}
+
+smokephp_object*
PHPQt::createOriginal(zval* zval_ptr, void* ptr)
{
smokephp_object* o = getSmokePHPObjectFromQt(ptr);
--- trunk/playground/bindings/phpqt/src/phpqt_internals.h #716070:716071
@@ -50,6 +50,7 @@
bool unmapSmokePHPObject(const zval* o);
smokephp_object* createObject(zval* zval_ptr, const void* ptr, const zend_class_entry* ce = 0, const Smoke::Index classId = 0);
+smokephp_object* cloneObject(zval* zval_ptr, smokephp_object* so, const void* copyPtr);
smokephp_object* createOriginal(zval* zval_ptr, void* ptr);
/*!
--- trunk/playground/bindings/phpqt/src/zend_handlers.cpp #716070:716071
@@ -32,6 +32,7 @@
zend_object_handlers php_qt_handler;
zend_object_handlers zend_orig_handler;
int (*originalConstantMethodHandler)(ZEND_OPCODE_HANDLER_ARGS);
+int (*originalCloneSpecCvHandler)(ZEND_OPCODE_HANDLER_ARGS);
opcode_handler_t *phpqt_original_opcode_handlers;
opcode_handler_t phpqt_opcode_handlers[PHPQT_OPHANDLER_COUNT];
@@ -185,6 +186,31 @@
}
+/*!
+ * calls the C++ copy constructor if available, and adds the smokephp_object to the new zval
+ */
+
+int
+ZendHandlers::cloneHandler( ZEND_OPCODE_HANDLER_ARGS )
+{
+ zend_op* opline = EX(opline);
+ // see CV_OF, _get_zval_ptr_ptr_cv
+ const zval* source = *EG(current_execute_data)->CVs[ EX(opline) ->op1.u.var];
+ int _ret = originalCloneSpecCvHandler(execute_data);
+
+ /* add Qt stuff */
+ smokephp_object* o = PHPQt::getSmokePHPObjectFromZval( source );
+ const void* copyPtr = construct_copy( o );
+ if ( !copyPtr )
+ php_error(E_ERROR, "%s can not be cloned", o->className().toAscii().constData());
+
+ smokephp_object* so = PHPQt::cloneObject( EX_T(opline->result.u.var).var.ptr, o, copyPtr );
+ if( smokephp_isQObject( so->classId() ) )
+ PHPQt::createMetaObject( so, EX_T(opline->result.u.var).var.ptr );
+
+ return _ret;
+}
+
void
ZendHandlers::installZendHandlers()
{
@@ -198,6 +224,14 @@
memcpy(phpqt_opcode_handlers, zend_opcode_handlers, sizeof(phpqt_opcode_handlers));
phpqt_original_opcode_handlers = zend_opcode_handlers;
zend_opcode_handlers = phpqt_opcode_handlers;
+
+ // overwrite the clone handler
+ originalCloneSpecCvHandler = phpqt_opcode_handlers[(ZEND_CLONE*25) + 20];
+ // ZEND_CLONE = 110 => 2750, line 29325
+ for(int i = 20; i <= 25; i++){
+ phpqt_opcode_handlers[(ZEND_CLONE*25) + i] = cloneHandler;
+ }
+
// ZEND_FETCH_CONSTANT = 99 => 2475, line 29050 in 5.2.4
phpqt_opcode_handlers[(ZEND_FETCH_CONSTANT*25) + 0] = constantHandler;
// replace and store ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_HANDLER, 29400
--- trunk/playground/bindings/phpqt/src/zend_handlers.h #716070:716071
@@ -56,6 +56,12 @@
int constantHandler(ZEND_OPCODE_HANDLER_ARGS);
/*!
+ * handler for cloning objects
+ */
+
+int cloneHandler(ZEND_OPCODE_HANDLER_ARGS);
+
+/*!
* install handlers
*/
More information about the Kde-bindings
mailing list