[Kde-bindings] playground/bindings/kimono

Arno Rehn kde at arnorehn.de
Wed Feb 28 14:17:01 UTC 2007


SVN commit 637998 by arnorehn:

* Don't include inherited signals/slots when building up the metaobject
* Added seperate methods for getting all the signals/slots of a class, including
  inherited ones. This is needed for InvokeCustomSlot() and SignalInvocation.Invoke()
* Changed qt_metacall to be more like the one genereted by moc:
	* First call qt_metacall of the base class
	* If the return value is postive, it was a C++ slot/signal/property, return
	* If the return value is negative, look for C# slots/signals/properties
	  and call them

CCMAIL: kde-bindings at kde.org



 M  +11 -0     ChangeLog  
 M  +92 -5     Qyoto.cs  
 M  +2 -2      SmokeInvocation.cs  
 M  +25 -30    qyoto.cpp  


--- trunk/playground/bindings/kimono/ChangeLog #637997:637998
@@ -1,3 +1,14 @@
+2007-02-28  Arno Rehn  <arno at arnorehn.de>
+
+	* Don't include inherited signals/slots when building up the metaobject
+	* Added seperate methods for getting all the signals/slots of a class, including
+	  inherited ones. This is needed for InvokeCustomSlot() and SignalInvocation.Invoke()
+	* Changed qt_metacall to be more like the one genereted by moc:
+		* First call qt_metacall of the base class
+		* If the return value is postive, it was a C++ slot/signal/property, return
+		* If the return value is negative, look for C# slots/signals/properties
+		  and call them
+
 2007-02-27  Richard Dale  <rdale at foton.es>
 
 	* Made the QMetaObject creation work correctly with nested subclasses
--- trunk/playground/bindings/kimono/Qyoto.cs #637997:637998
@@ -209,18 +209,56 @@
 				type = return_type;
 		}
 		
+		// this method is only used when we build up our meta object.
+		// it only returns declared slots
 		public static Dictionary<string, CPPMethod> GetSlotSignatures(Type t) {
+			/// This Hashtable contains the slots of a class. The C++ type signature is the key, the appropriate array with the MethodInfo, signature and return type the value.
+			Dictionary<string, CPPMethod> slots = new Dictionary<string, CPPMethod>();
+			
+			// only declared members
+			MethodInfo[] mis = t.GetMethods(	BindingFlags.Instance 
+												| BindingFlags.Static 
+												| BindingFlags.Public 
+												| BindingFlags.NonPublic
+												| BindingFlags.DeclaredOnly);
+			
+			foreach (MethodInfo mi in mis) {
+				if (IsSmokeClass(mi.DeclaringType)) continue;
+				object[] attributes = mi.GetCustomAttributes(typeof(Q_SLOT), false);
+				foreach (Q_SLOT attr in attributes) {
+					CPPMethod cppinfo = new CPPMethod();
+					
+					string sig = attr.Signature;
+					if (sig == "")
+						sig = SignatureFromMethodInfo(mi);
+					GetCPPMethodInfo(sig, out cppinfo.signature, out cppinfo.type);
+					
+					cppinfo.mi = mi;
+					
+					if (mi.GetCustomAttributes(typeof(Q_SCRIPTABLE), false).Length > 0)
+						cppinfo.scriptable = true;
+					
+					slots.Add(cppinfo.signature, cppinfo);
+					break;
+				}
+			}
+			return slots;
+		}
+		
+		// this method is used to get _all_ the slots of a class
+		// this is needed by SmokeInvocation.InvokeCustomSlot()
+		public static Dictionary<string, CPPMethod> GetAllSlotSignatures(Type t) {
 			/// Remove the old object if it already exists
 			classes.Remove(t.ToString());
 			
 			/// This Hashtable contains the slots of a class. The C++ type signature is the key, the appropriate array with the MethodInfo, signature and return type the value.
 			Dictionary<string, CPPMethod> slots = new Dictionary<string, CPPMethod>();
 			
+			// also include inherited members
 			MethodInfo[] mis = t.GetMethods(	BindingFlags.Instance 
 												| BindingFlags.Static 
 												| BindingFlags.Public 
-												| BindingFlags.NonPublic
-												/*| BindingFlags.DeclaredOnly */);
+												| BindingFlags.NonPublic);
 			
 			foreach (MethodInfo mi in mis) {
 				if (IsSmokeClass(mi.DeclaringType)) continue;
@@ -247,8 +285,8 @@
 			return slots;
 		}
 		
-		
-		/// returns a Hastable with the MethodInfo as a key and the array with the MethodInfo, signature and return type the value.
+		// this method is again only used when we build up our meta object.
+		// it only returns declared signals
 		public static Dictionary<MethodInfo, CPPMethod> GetSignalSignatures(Type t) {
 			Dictionary<MethodInfo, CPPMethod> signals = new Dictionary<MethodInfo, CPPMethod>();
 			if (IsSmokeClass(t)) {
@@ -264,8 +302,14 @@
 			}
 
 			Type iface = propertyInfo.PropertyType;
-			MethodInfo[] mis = iface.GetMethods();
 			
+			// don't get inherited methods
+			MethodInfo[] mis = iface.GetMethods(BindingFlags.Instance
+								| BindingFlags.Static
+								| BindingFlags.DeclaredOnly
+								| BindingFlags.Public
+								| BindingFlags.NonPublic);
+			
 			/// the interface has no signals...
 			if (mis.Length == 0)
 				return signals;
@@ -290,6 +334,49 @@
 			return signals;
 		}
 		
+		// this method returns _all_ the signals of a class, including inherited ones
+		// used by SignalInvocation.Invoke()
+		public static Dictionary<MethodInfo, CPPMethod> GetAllSignalSignatures(Type t) {
+			Dictionary<MethodInfo, CPPMethod> signals = new Dictionary<MethodInfo, CPPMethod>();
+			if (IsSmokeClass(t))
+				return signals;
+			
+			Type currentType = t;
+			while (!IsSmokeClass(currentType)) {
+				PropertyInfo propertyInfo = currentType.GetProperty(	"Emit", 
+													BindingFlags.Instance 
+													| BindingFlags.NonPublic
+													| BindingFlags.DeclaredOnly );
+				if (propertyInfo == null) {
+					currentType = currentType.BaseType;
+					continue;
+				}
+				
+				Type iface = propertyInfo.PropertyType;
+				MethodInfo[] mis = iface.GetMethods();
+				
+				foreach (MethodInfo mi in mis) {
+					object[] attributes = mi.GetCustomAttributes(typeof(Q_SIGNAL), false);
+					foreach (Q_SIGNAL attr in attributes) {
+						CPPMethod cppinfo = new CPPMethod();
+						string sig = attr.Signature;
+						if (sig == "")
+							sig = SignatureFromMethodInfo(mi).Trim();
+						GetCPPMethodInfo(sig, out cppinfo.signature, out cppinfo.type);
+						cppinfo.mi = mi;
+						
+						if (mi.GetCustomAttributes(typeof(Q_SCRIPTABLE), false).Length > 0)
+							cppinfo.scriptable = true;
+						
+						signals.Add(cppinfo.mi, cppinfo);
+					}
+				}
+				
+				currentType = currentType.BaseType;
+			}
+			
+			return signals;
+		}
 		public static Type GetSignalsInterface(Type t) {
 			PropertyInfo pi = t.GetProperty("Emit", BindingFlags.Instance | BindingFlags.NonPublic);
 			return pi.PropertyType;
--- trunk/playground/bindings/kimono/SmokeInvocation.cs #637997:637998
@@ -247,7 +247,7 @@
 #endif
 			Dictionary<string, Qyoto.CPPMethod> slotTable;
 			if (!Qyoto.classes.TryGetValue(className, out slotTable)) {
-				slotTable = Qyoto.GetSlotSignatures(qobj.GetType());
+				slotTable = Qyoto.GetAllSlotSignatures(qobj.GetType());
 			}
 			MethodInfo slot;
 			try {
@@ -554,7 +554,7 @@
 			IMethodReturnMessage returnMessage = (IMethodReturnMessage) message;
 			MethodReturnMessageWrapper returnValue = new MethodReturnMessageWrapper((IMethodReturnMessage) returnMessage); 
 			GCHandle instanceHandle = GCHandle.Alloc(_instance);
-			Dictionary<MethodInfo, Qyoto.CPPMethod> signals = Qyoto.GetSignalSignatures(_instance.GetType());
+			Dictionary<MethodInfo, Qyoto.CPPMethod> signals = Qyoto.GetAllSignalSignatures(_instance.GetType());
 			
 			/// should not happen
 			if (signals == null) {
--- trunk/playground/bindings/kimono/qyoto.cpp #637997:637998
@@ -1630,45 +1630,40 @@
 
 
 int qt_metacall(void* obj, int _c, int _id, void* _o) {
-	// get obj metaobject with a virtual call
 	smokeqyoto_object* o = value_obj_info(obj);
-    QObject *qobj = (QObject*)o->ptr;
+	
+	Smoke::Index nameId = o->smoke->idMethodName("qt_metacall$$?");
+	Smoke::Index meth = o->smoke->findMethod(o->classId, nameId);
+	if(meth > 0) {
+		Smoke::Method &m = o->smoke->methods[o->smoke->methodMaps[meth].method];
+		Smoke::ClassFn fn = o->smoke->classes[m.classId].classFn;
+		Smoke::StackItem i[4];
+		i[1].s_enum = _c;
+		i[2].s_int = _id;
+		i[3].s_voidp = _o;
+		(*fn)(m.method, o->ptr, i);
+		
+		int ret = i[0].s_int;
+		if (ret < 0)
+			return ret;
+	} else {
+		// Should never happen..
+		qFatal("Cannot find %s::qt_metacall() method\n", 
+			o->smoke->classes[o->classId].className );
+	}
+
+	QObject *qobj = (QObject*)o->ptr;
+	// get obj metaobject with a virtual call
 	const QMetaObject *metaobject = qobj->metaObject();
 	
-	// get method count and offset
+	// get method/property count
 	int count = 0;
-	int offset = 0;
 	if (_c == QMetaObject::InvokeMetaMethod) {
 		count = metaobject->methodCount();
-		offset = metaobject->methodOffset();
 	} else {
 		count = metaobject->propertyCount();
-		offset = metaobject->propertyOffset();
 	}
 	
-
-	// if id < offset call base version
-	if (_id < offset || (*IsSmokeClass)(obj)) {
-		// Assume the target slot is a C++ one
-		Smoke::Index nameId = o->smoke->idMethodName("qt_metacall$$?");
-		Smoke::Index meth = o->smoke->findMethod(o->classId, nameId);
-		if(meth > 0) {
-			Smoke::Method &m = o->smoke->methods[o->smoke->methodMaps[meth].method];
-			Smoke::ClassFn fn = o->smoke->classes[m.classId].classFn;
-			Smoke::StackItem i[4];
-			i[1].s_enum = _c;
-			i[2].s_int = _id;
-			i[3].s_voidp = _o;
-			(*fn)(m.method, o->ptr, i);
-			
-			return i[0].s_int;
-		}
-		
-		// Should never happen..
-		qFatal("Cannot find %s::qt_metacall() method\n", 
-			o->smoke->classes[o->classId].className );
-	}
-
 	if (_c == QMetaObject::InvokeMetaMethod) {
 		// retrieve method signature from id
 		QMetaMethod method = metaobject->method(_id);
@@ -1677,7 +1672,7 @@
 		
 		if (method.methodType() == QMetaMethod::Signal) {
 			metaobject->activate(qobj, _id, (void**) _o);
-			return _id - (count - offset);
+			return _id - count;
 		}
 	
 		int items;



More information about the Kde-bindings mailing list