[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