[Kde-bindings] playground/bindings/kimono

Richard Dale Richard_Dale at tipitina.demon.co.uk
Mon May 29 20:05:10 UTC 2006


SVN commit 546351 by rdale:

* More fixes from Paulo:
* To avoid virtual method dispatch resulting in infinite loop, the
  meta object instance is now created in c++ code using smoke (just as
  in qtruby).
* Qyoto.GetMetaObject now works for Qt types as well
* Decommented code in set_obj_info. This function is used by the
  return value marshaller for non-primitive types and by
  make_metaObject.

CCMAIL: kde-bindings at kde.org



 M  +9 -0      ChangeLog  
 M  +1 -1      SmokeInvocation.cs  
 M  +42 -33    qyoto.cpp  
 M  +36 -34    qyoto/Qyoto.cs  


--- trunk/playground/bindings/kimono/ChangeLog #546350:546351
@@ -1,5 +1,14 @@
 2006-05-29  Richard Dale  <rdale at foton.es>
 
+	* More fixes from Paulo:
+	* To avoid virtual method dispatch resulting in infinite loop, the
+	  meta object instance is now created in c++ code using smoke (just as
+	  in qtruby).
+	* Qyoto.GetMetaObject now works for Qt types as well
+	* Decommented code in set_obj_info. This function is used by the
+	  return value marshaller for non-primitive types and by
+	  make_metaObject.
+
 	* Added patch from Paulo Capriotti to create a QMetaObject at runtime
 	  for a Qyoto class with custom slots and/or signals
 
--- trunk/playground/bindings/kimono/SmokeInvocation.cs #546350:546351
@@ -200,7 +200,7 @@
 			Type klass = Type.GetType(className);
 
 			Type[] constructorParamTypes = new Type[1];
-			constructorParamTypes[0] = Type.GetType("System.Type");
+			constructorParamTypes[0] = typeof(Type);
 			ConstructorInfo constructorInfo = klass.GetConstructor(BindingFlags.NonPublic 
 					| BindingFlags.Instance, null, new Type[ ] { typeof( Type ) } , null);
 			if (constructorInfo == null) {
--- trunk/playground/bindings/kimono/qyoto.cpp #546350:546351
@@ -49,7 +49,7 @@
 #include "smoke.h"
 
 #define QYOTO_VERSION "0.0.1"
-// #define DEBUG
+#define DEBUG
 
 extern Smoke *qt_Smoke;
 extern void init_qt_Smoke();
@@ -164,10 +164,9 @@
 void *
 set_obj_info(const char * className, smokeqyoto_object * o)
 {
-//	void * obj = (*CreateInstance)(className);
-//	(*SetSmokeObject)(obj, o);
-//	return obj;
-	return 0;
+	void * obj = (*CreateInstance)(className);
+	(*SetSmokeObject)(obj, o);
+	return obj;
 }
 
 Marshall::HandlerFn getMarshallFn(const SmokeType &type);
@@ -942,11 +941,8 @@
 			strcmp(m.signature(), signatureStr) == 0)
 			break;
 	}
-
-#ifdef DEBUG  
+	
 	printf("emitting signal %d\n", i);
-#endif
-
 	EmitSignal signal(qobj, i, items, args, sp);
 	signal.next();
 
@@ -958,32 +954,45 @@
 }
 
 
-void * 
-make_metaObject(QMetaObject* parent, const char* stringdata, const uint* data) {
-#ifdef DEBUG
-	printf("parent = %x\n", parent);
+void* make_metaObject(void* obj, const char* stringdata, const uint* data) {
 	printf("stringdata = %s\n", stringdata);
 	printf("data = %x\n", data);
-#endif
-  // create a QMetaObject on the stack
-  QMetaObject tmp = {{
-    parent,
-    stringdata,
-    data,
-    0
-  }};
-  
-  // copy it to the heap
-  QMetaObject* meta = new QMetaObject;
-  *meta = tmp;
-  
-  // create smoke object
-  smokeqyoto_object* m = (smokeqyoto_object*)malloc(sizeof(smokeqyoto_object));
-  m->smoke = qt_Smoke;
-  m->classId = qt_Smoke->idClass("QMetaObject");
-  m->ptr = meta;
-  
-  return m;
+	
+	smokeqyoto_object* o = value_obj_info(obj);
+	Smoke::Index nameId = o->smoke->idMethodName("metaObject");
+	Smoke::Index meth = o->smoke->findMethod(o->classId, nameId);
+	if (meth <= 0) {
+		// Should never happen..
+		return 0;
+	}
+	
+	Smoke::Method &methodId = o->smoke->methods[o->smoke->methodMaps[meth].method];
+	Smoke::ClassFn fn = o->smoke->classes[methodId.classId].classFn;
+	Smoke::StackItem i[1];
+	(*fn)(methodId.method, o->ptr, i);
+	
+	QMetaObject* parent = (QMetaObject*) i[0].s_voidp;
+	
+	// create a QMetaObject on the stack
+	QMetaObject tmp = {{
+		parent,
+		stringdata,
+		data,
+		0
+	}};
+	
+	// copy it to the heap
+	QMetaObject* meta = new QMetaObject;
+	*meta = tmp;
+	
+	// create smoke object
+	smokeqyoto_object* m = (smokeqyoto_object*)malloc(sizeof(smokeqyoto_object));
+	m->smoke = qt_Smoke;
+	m->classId = qt_Smoke->idClass("QMetaObject");
+	m->ptr = meta;
+	
+	// create wrapper C# instance
+	return set_obj_info("Qt.QMetaObject", m);
 }
 
 void
--- trunk/playground/bindings/kimono/qyoto/Qyoto.cs #546350:546351
@@ -21,7 +21,7 @@
 		/// This hashtable has classe names as keys, and QMetaObjects as values
 		static Hashtable metaObjects = new Hashtable();
 		
-		public static void GetSlotSignatures(Type t) {
+		public static Hashtable GetSlotSignatures(Type t) {
 			
 			/// Remove the old object if it already exists
 			classes.Remove(t.Name);
@@ -40,6 +40,7 @@
 			}
 			
 			classes.Add(t.Name, slots);
+			return slots;
 		}
 		
 		public static string[] GetSignalSignatures(Type t) {
@@ -174,61 +175,62 @@
 			}
 		}
     
-		public static QMetaObject MakeMetaObject(Type t) {
-#if DEBUG
-			Console.WriteLine("ENTER: MakeMetaObject.  t => {0}", t);
-#endif
+		public static QMetaObject MakeMetaObject(Type t, QObject o) {
+			if (t == null) return null;
 		
-			if (t == null || typeof(QObject).IsAssignableFrom(t)) return null;
-		
 			string className = t.ToString();
 			Hashtable slotTable = (Hashtable)classes[className];
+			
 		
 			ICollection slots;
 			if (slotTable != null)
 				slots = slotTable.Values;
 			else {
 				// build slot table
-				GetSlotSignatures(t);
-				slotTable = (Hashtable)classes[className];
-				slots = slotTable.Values;
+				slots = GetSlotSignatures(t).Values;
 			}
-		
+
 			string[] signals = GetSignalSignatures(t);
 			QyotoMetaData metaData = new QyotoMetaData(className, signals, slots);
-			GCHandle parentMetaObject = GCHandle.Alloc(GetMetaObject(t.BaseType));
-			IntPtr metaSmokeObject;
-		
+			
+			GCHandle objHandle = GCHandle.Alloc(o);
+			IntPtr metaObject;
+			
 			unsafe {
 				fixed (byte* stringdata = metaData.StringData)
 				fixed (int* data = metaData.Data) {
-					metaSmokeObject = make_metaObject((IntPtr)parentMetaObject, (IntPtr)stringdata, (IntPtr)data);
+					metaObject = make_metaObject((IntPtr)objHandle, (IntPtr)stringdata, (IntPtr)data);
 				}
 			}
       
-			// create a new C# QMetaObject and replace its
-			// inner _smokeObject with that returned from make_metaObject
-			QMetaObject res = new QMetaObject();
-			FieldInfo fieldInfo = typeof(QMetaObject).GetField(  "_smokeObject", 
-																BindingFlags.NonPublic 
-																| BindingFlags.GetField
-																| BindingFlags.Instance );
-			((GCHandle)fieldInfo.GetValue(res)).Free();
-			fieldInfo.SetValue(res, metaSmokeObject);
-		
-#if DEBUG
-			Console.WriteLine("LEAVE MakeMetaObject");
-#endif
+			QMetaObject res = (QMetaObject)((GCHandle) metaObject).Target;
 			return res;
 		}
     
-		public static QMetaObject GetMetaObject(Type t) {
-			QMetaObject res = (QMetaObject)metaObjects[t.ToString()];
-			if (res == null) {
-				res = MakeMetaObject(t);
-				metaObjects[t.ToString()] = res;
+		public static QMetaObject GetMetaObject(Type t, QObject o) {
+			object[] attr = t.GetCustomAttributes(typeof(SmokeClass), false);
+			if (attr.Length > 0) {
+				// qt class: simply call the MetaObject method
+				MethodInfo metaObjectMethod = t.GetMethod("MetaObject", BindingFlags.Public | BindingFlags.Instance);
+				if (metaObjectMethod == null) {
+					// this should never happen
+					Console.WriteLine("** Cannot find MetaObject method **");
+					return null;
+				}
+				else {
+					return (QMetaObject)metaObjectMethod.Invoke(o, new object[] {});
+				}
 			}
-			return res;
+			else {
+				// user defined class: retrieve QMetaObject from the hashtable
+				QMetaObject res = (QMetaObject)metaObjects[t.ToString()];
+				if (res == null) {
+					// create QMetaObject
+					res = MakeMetaObject(t, o);
+					metaObjects[t.ToString()] = res;
+				}
+				return res;
+			}
 		}
 	}
 	



More information about the Kde-bindings mailing list