[Kde-bindings] playground/bindings/kimono

Richard Dale Richard_Dale at tipitina.demon.co.uk
Sat Mar 24 12:20:50 UTC 2007


SVN commit 646050 by rdale:

* The 'IsSmokeClass()' test now uses the Smoke class data cache
* Renamed the method to retrieve a C# instance given a pointer to the C++
  instance as 'GetInstance(). Given it an a boolean argument 'allInstances'
  and if false, GetInstance() will only return instances that are custom 
  subclasses of Qyoto classes. This is useful when dealing with overriden
  virtual method callbacks, as only custom subclasses can have their own
  slots or overriden virtual methods.
* These two improvements give a 2-3 times speed up, and Qyoto now uses 
  about 6 times less mill than it did a week ago.

CCMAIL: kde-bindings at kde.org



 M  +12 -0     ChangeLog  
 M  +7 -17     Qyoto.cs  
 M  +3 -8      SmokeInvocation.cs  
 M  +54 -21    SmokeMarshallers.cs  
 M  +11 -32    qyoto.cpp  
 M  +1 -1      qyoto.h  


--- trunk/playground/bindings/kimono/ChangeLog #646049:646050
@@ -1,3 +1,15 @@
+2007-03-24  Richard Dale  <rdale at foton.es>
+
+	* The 'IsSmokeClass()' test now uses the Smoke class data cache
+	* Renamed the method to retrieve a C# instance given a pointer to the C++
+	  instance as 'GetInstance(). Given it an a boolean argument 'allInstances'
+	  and if false, GetInstance() will only return instances that are custom 
+	  subclasses of Qyoto classes. This is useful when dealing with overriden
+	  virtual method callbacks, as only custom subclasses can have their own
+	  slots or overriden virtual methods.
+	* These two improvements give a 2-3 times speed up, and Qyoto now uses 
+	  about 6 times less mill than it did a week ago.
+
 2007-03-23  Richard Dale  <rdale at foton.es>
 
 	* Cache various items in a dictionary with a key of the Smoke class's
--- trunk/playground/bindings/kimono/Qyoto.cs #646049:646050
@@ -138,16 +138,6 @@
 			return 0;
 		}
 		
-		public static bool IsSmokeClass(Type t) {
-			object[] attr = t.GetCustomAttributes(typeof(SmokeClass), false);
-			return attr.Length > 0;
-		}
-		
-		public static bool IsSmokeClass(IntPtr obj) {
-			object qobj = ((GCHandle) obj).Target;
-			return IsSmokeClass(qobj.GetType());
-		}
-		
 		public static string GetPrimitiveString(Type type) {
 			string typeString = type.ToString();
 			string ret = type.ToString();
@@ -256,7 +246,7 @@
 												| BindingFlags.DeclaredOnly);
 			
 			foreach (MethodInfo mi in mis) {
-				if (IsSmokeClass(mi.DeclaringType)) continue;
+				if (SmokeMarshallers.IsSmokeClass(mi.DeclaringType)) continue;
 				object[] attributes = mi.GetCustomAttributes(typeof(Q_SLOT), false);
 				foreach (Q_SLOT attr in attributes) {
 					CPPMethod cppinfo = new CPPMethod();
@@ -294,7 +284,7 @@
 												| BindingFlags.NonPublic);
 			
 			foreach (MethodInfo mi in mis) {
-				if (IsSmokeClass(mi.DeclaringType)) continue;
+				if (SmokeMarshallers.IsSmokeClass(mi.DeclaringType)) continue;
 				object[] attributes = mi.GetCustomAttributes(typeof(Q_SLOT), false);
 				foreach (Q_SLOT attr in attributes) {
 					CPPMethod cppinfo = new CPPMethod();
@@ -322,7 +312,7 @@
 		// it only returns declared signals
 		public static Dictionary<MethodInfo, CPPMethod> GetSignalSignatures(Type t) {
 			Dictionary<MethodInfo, CPPMethod> signals = new Dictionary<MethodInfo, CPPMethod>();
-			if (IsSmokeClass(t)) {
+			if (SmokeMarshallers.IsSmokeClass(t)) {
 				return signals;
 			}
 			
@@ -371,11 +361,11 @@
 		// used by SignalInvocation.Invoke()
 		public static Dictionary<MethodInfo, CPPMethod> GetAllSignalSignatures(Type t) {
 			Dictionary<MethodInfo, CPPMethod> signals = new Dictionary<MethodInfo, CPPMethod>();
-			if (IsSmokeClass(t))
+			if (SmokeMarshallers.IsSmokeClass(t))
 				return signals;
 			
 			Type currentType = t;
-			while (!IsSmokeClass(currentType)) {
+			while (!SmokeMarshallers.IsSmokeClass(currentType)) {
 				PropertyInfo propertyInfo = currentType.GetProperty(	"Emit", 
 													BindingFlags.Instance 
 													| BindingFlags.NonPublic
@@ -428,7 +418,7 @@
 			Dictionary<PropertyInfo, CPPProperty> props = new Dictionary<PropertyInfo, CPPProperty>();
 			
 			foreach (PropertyInfo pi in t.GetProperties()) {
-				if (IsSmokeClass(pi.DeclaringType)) continue;
+				if (SmokeMarshallers.IsSmokeClass(pi.DeclaringType)) continue;
 				object[] attrs = pi.GetCustomAttributes(typeof(Q_PROPERTY), false);
 				if (attrs.Length != 0) {
 					Q_PROPERTY attr = (Q_PROPERTY) attrs[0];
@@ -454,7 +444,7 @@
 			if (t == null) return null;
 
 			QMetaObject parentMeta = null;
-			if (	!IsSmokeClass(t.BaseType)
+			if (	!SmokeMarshallers.IsSmokeClass(t.BaseType)
 					&& !metaObjects.TryGetValue(t.BaseType.Name, out parentMeta) ) 
 			{
 				// create QMetaObject
--- trunk/playground/bindings/kimono/SmokeInvocation.cs #646049:646050
@@ -71,8 +71,7 @@
 		static private MethodInfo metaObjectMethod = typeof(QObject).GetMethod("MetaObject", BindingFlags.Instance | BindingFlags.Public);
 		
 		static void AddOverridenMethods(Type klass) {
-			object[] attributes = klass.GetCustomAttributes(typeof(SmokeClass), false);
-			if (attributes.Length > 0) {
+			if (SmokeMarshallers.IsSmokeClass(klass)) {
 				return;
 			}
 
@@ -122,8 +121,7 @@
 				}
 
 				klass = klass.BaseType;
-				attributes = klass.GetCustomAttributes(typeof(SmokeClass), false);
-			} while (attributes.Length == 0);
+			} while (!SmokeMarshallers.IsSmokeClass(klass));
 		}
 
 		public static IntPtr OverridenMethod(IntPtr instance, string method) {
@@ -398,10 +396,7 @@
 		{
 			_classToProxy = classToProxy;
 			_instance = instance;
-			object[] smokeClass = classToProxy.GetCustomAttributes(typeof(SmokeClass), true);
-			if (smokeClass.Length > 0) {
-				_className = ((SmokeClass) smokeClass[0]).Signature;
-			}
+			_className = SmokeMarshallers.SmokeClassName(classToProxy);
 
 			if (_instance != null) {
 				AddOverridenMethods(_instance.GetType());
--- trunk/playground/bindings/kimono/SmokeMarshallers.cs #646049:646050
@@ -86,7 +86,7 @@
 		public static extern void InstallUnmapPointer(FromIntPtr callback);
 		
 		[DllImport("libqyoto", CharSet=CharSet.Ansi)]
-		public static extern void InstallGetPointerObject(GetIntPtr callback);
+		public static extern void InstallGetInstance(GetInstanceFn callback);
 
 		[DllImport("libqyoto", CharSet=CharSet.Ansi)]
 		public static extern void InstallCreateInstance(CreateInstanceFn callback);
@@ -95,9 +95,6 @@
 		public static extern void InstallInvokeCustomSlot(InvokeCustomSlotFn callback);
 		
 		[DllImport("libqyoto", CharSet=CharSet.Ansi)]
-		public static extern bool InstallIsSmokeClass(IsSmokeClassFn callback);
-		
-		[DllImport("libqyoto", CharSet=CharSet.Ansi)]
 		public static extern bool InstallGetProperty(OverridenMethodFn callback);
 		
 		[DllImport("libqyoto", CharSet=CharSet.Ansi)]
@@ -123,7 +120,7 @@
 
 		[DllImport("libqyoto", CharSet=CharSet.Ansi)]
 		public static extern void InstallStringBuilderFromQString(SetIntPtrFromCharStar callback);
-		
+
 		[DllImport("libqyoto", CharSet=CharSet.Ansi)]
 		public static extern void InstallOverridenMethod(OverridenMethodFn callback);
 
@@ -168,8 +165,8 @@
 		public delegate void FromIntPtr(IntPtr ptr);
 		public delegate void MapPointerFn(IntPtr instance, IntPtr ptr, bool createStrongReference);
 		public delegate IntPtr CreateInstanceFn(string className);
+		public delegate IntPtr GetInstanceFn(IntPtr ptr, bool allInstances);
 		public delegate void InvokeCustomSlotFn(IntPtr obj, string slot, IntPtr stack, IntPtr ret);
-		public delegate bool IsSmokeClassFn(IntPtr obj);
 		public delegate IntPtr GetIntPtrFromString(string str);
 		public delegate string GetStringFromIntPtr(IntPtr ptr);
 		public delegate void SetIntPtrFromCharStar(IntPtr ptr, string str);
@@ -301,14 +298,16 @@
 			}
 		}
 		
-		public static IntPtr GetPointerObject(IntPtr ptr) {
+		// If 'allInstances' is false then only return a result if the instance a custom subclass
+		// of a Qyoto class and therefore could have custom slots or overriden methods
+		public static IntPtr GetInstance(IntPtr ptr, bool allInstances) {
 			WeakReference weakRef;
 			if (!pointerMap.TryGetValue(ptr, out weakRef)) {
 #if DEBUG
 				if (	(QDebug.DebugChannel() & QtDebugChannel.QTDB_GC) != 0
 						&& QDebug.debugLevel >= DebugLevel.Extensive ) 
 				{
-					Console.WriteLine("GetPointerObject() pointerMap[0x{0:x8}] == null", (int) ptr);
+					Console.WriteLine("GetInstance() pointerMap[0x{0:x8}] == null", (int) ptr);
 				}
 #endif
 				return (IntPtr) 0;
@@ -319,16 +318,18 @@
 				if (	(QDebug.DebugChannel() & QtDebugChannel.QTDB_GC) != 0
 						&& QDebug.debugLevel >= DebugLevel.Extensive ) 
 				{
-					Console.WriteLine("GetPointerObject() weakRef null ptr: 0x{0:x8}", (int) ptr);
+					Console.WriteLine("GetInstance() weakRef null ptr: 0x{0:x8}", (int) ptr);
 				}
 #endif
 				return (IntPtr) 0;
-			} else if (weakRef.IsAlive) {
+			} else if (	weakRef.IsAlive 
+						&& (allInstances || !IsSmokeClass(weakRef.Target.GetType())) ) 
+			{
 #if DEBUG
 				if (	(QDebug.DebugChannel() & QtDebugChannel.QTDB_GC) != 0
 						&& QDebug.debugLevel >= DebugLevel.Extensive ) 
 				{
-					Console.WriteLine("GetPointerObject() weakRef.IsAlive 0x{0:x8} -> {1}", (int) ptr, weakRef.Target);
+					Console.WriteLine("GetInstance() weakRef.IsAlive 0x{0:x8} -> {1}", (int) ptr, weakRef.Target);
 				}
 #endif
 
@@ -343,7 +344,7 @@
 				if (	(QDebug.DebugChannel() & QtDebugChannel.QTDB_GC) != 0
 						&& QDebug.debugLevel >= DebugLevel.Extensive ) 
 				{
-					Console.WriteLine("GetPointerObject() weakRef dead ptr: 0x{0:x8}", (int) ptr);
+					Console.WriteLine("GetInstance() weakRef dead ptr: 0x{0:x8}", (int) ptr);
 				}
 #endif
 				return (IntPtr) 0;
@@ -358,19 +359,36 @@
 			public FieldInfo smokeObjectField;
 		}
 
-		static Dictionary<Type, SmokeClassData> smokeClassCache = new Dictionary<Type, SmokeClassData> ();
+		private static Dictionary<Type, SmokeClassData> smokeClassCache = new Dictionary<Type, SmokeClassData> ();
 		
 		private static SmokeClassData GetSmokeClassData(Type t) {
-			SmokeClassData result;
+			SmokeClassData result = null;
 
 			if (!smokeClassCache.TryGetValue(t, out result)) {
-				result = new SmokeClassData();
+				string className = null;
 
 				object[] attr = t.GetCustomAttributes(typeof(SmokeClass), false);
 				if (attr.Length > 0) {
-					result.className = ((SmokeClass) attr[0]).signature;
+					className = ((SmokeClass) attr[0]).signature;
+				} else {
+					attr = t.GetCustomAttributes(typeof(SmokeClass), true);
+					if (attr.Length == 0) {
+						// The class is a superclass of a Qyoto class such as
+						// MarshalByRefObject, so save a null value to avoid
+						// needing to do the above test again
+						smokeClassCache[t] = null;
+						return null;
+					}
 				}
 
+				result = new SmokeClassData();
+				result.className = className;
+				smokeClassCache[t] = result;
+
+				if (t.IsInterface) {
+					return result;
+				}
+
 				Type[] paramTypes = new Type[1];
 				paramTypes[0] = typeof(Type);
 				result.constructorParamTypes = new object[] { paramTypes[0] };
@@ -396,12 +414,29 @@
 														BindingFlags.NonPublic 
 														| BindingFlags.GetField
 														| BindingFlags.Instance );
-				smokeClassCache[t] = result;
 			}
 
 			return result;
 		}
 
+		// The class is not a custom subclass of a Qyoto class, and also is not
+		// a superclass of a Qyoto class, such as a MarshalByRefObject.
+		public static bool IsSmokeClass(Type klass) {
+			SmokeClassData data = GetSmokeClassData(klass);
+			return data != null && data.className != null;
+		}
+
+		// The C++ class name signature of a Smoke class or interface
+		public static string SmokeClassName(Type klass) {
+			SmokeClassData data = GetSmokeClassData(klass);
+			while (data.className == null) {
+				klass = klass.BaseType;
+				data = GetSmokeClassData(klass);
+			}
+			
+			return data.className;
+		}
+
 		// CreateInstance() creates a wrapper instance around a C++ instance which
 		// has been created in C++ code, and not via a Qyoto C# constructor call.
 		// It takes the class name string and obtains its Type. Then it finds the
@@ -602,7 +637,7 @@
 		
 		static private MapPointerFn mapPointer = new MapPointerFn(MapPointer);
 		static private FromIntPtr unmapPointer = new FromIntPtr(UnmapPointer);
-		static private GetIntPtr getPointerObject = new GetIntPtr(GetPointerObject);
+		static private GetInstanceFn getInstance = new GetInstanceFn(GetInstance);
 		
 		static private GetIntPtr intPtrToCharStarStar = new GetIntPtr(IntPtrToCharStarStar);
 		static private GetStringFromIntPtr intPtrToString = new GetStringFromIntPtr(IntPtrToString);
@@ -631,7 +666,6 @@
 
 		static private CreateInstanceFn createInstance = new CreateInstanceFn(CreateInstance);
 		static private InvokeCustomSlotFn invokeCustomSlot = new InvokeCustomSlotFn(SmokeInvocation.InvokeCustomSlot);
-		static private IsSmokeClassFn isSmokeClass = new IsSmokeClassFn(Qyoto.IsSmokeClass);
 		
 		static private OverridenMethodFn getProperty = new OverridenMethodFn(GetProperty);
 		static private SetPropertyFn setProperty = new SetPropertyFn(SetProperty);
@@ -644,7 +678,7 @@
 			
 			InstallMapPointer(mapPointer);
 			InstallUnmapPointer(unmapPointer);
-			InstallGetPointerObject(getPointerObject);
+			InstallGetInstance(getInstance);
 
 			InstallIntPtrToCharStarStar(intPtrToCharStarStar);
 			InstallIntPtrToCharStar(intPtrToString);
@@ -671,7 +705,6 @@
 
 			InstallCreateInstance(createInstance);
 			InstallInvokeCustomSlot(invokeCustomSlot);
-			InstallIsSmokeClass(isSmokeClass);
 			
 			InstallGetProperty(getProperty);
 			InstallSetProperty(setProperty);
--- trunk/playground/bindings/kimono/qyoto.cpp #646049:646050
@@ -69,13 +69,12 @@
 
 static MapPointerFn MapPointer;
 static FromIntPtr UnmapPointer;
-static GetIntPtr GetPointerObject;
+static GetInstanceFn GetInstance;
 
 static OverridenMethodFn OverridenMethod;
 static InvokeMethodFn InvokeMethod;
 static CreateInstanceFn CreateInstance;
 static InvokeCustomSlotFn InvokeCustomSlot;
-static IsSmokeClassFn IsSmokeClass;
 
 static OverridenMethodFn GetProperty;
 static SetPropertyFn SetProperty;
@@ -322,7 +321,7 @@
 }
 
 void * getPointerObject(void *ptr) {
-	return (*GetPointerObject)(ptr);
+	return (*GetInstance)(ptr, true);
 }
 
 void unmapPointer(smokeqyoto_object *o, Smoke::Index classId, void *lastptr) {
@@ -975,6 +974,12 @@
     }
 
 	bool callMethod(Smoke::Index method, void *ptr, Smoke::Stack args, bool /*isAbstract*/) {
+		void * obj = (*GetInstance)(ptr, false);
+
+		if (obj == 0) {
+			return false;
+		}
+
 		Smoke::Method & meth = smoke->methods[method];
 		QByteArray signature(smoke->methodNames[meth.name]);
 		signature += "(";
@@ -996,26 +1001,6 @@
 						(const char *) signature );
 			fflush(stdout);
 		}
-
-		void * obj = getPointerObject(ptr);
-
-		if (obj == 0) {
-			if( do_debug & qtdb_virtual ) {  // if not in global destruction
-				printf("Cannot find object for virtual method %p -> %p\n", ptr, obj);
-			}
-
-			return false;
-		}
-
-		smokeqyoto_object *o = value_obj_info(obj);
-
-		if (o == 0) {
-			if( do_debug & qtdb_virtual ) {  // if not in global destruction
-				printf("Cannot find object for virtual method %p -> %p\n", ptr, obj);
-			}
-
-			return false;
-		}
 		
 		if (strcmp(signature, "qt_metacall(QMetaObject::Call, int, void**)") == 0) {
 			QMetaObject::Call _c = (QMetaObject::Call)args[1].s_int;
@@ -1378,12 +1363,12 @@
 }
 
 void 
-InstallGetPointerObject(GetIntPtr callback)
+InstallGetInstance(GetInstanceFn callback)
 {
-	GetPointerObject = callback;
+	GetInstance = callback;
 }
 
-void 
+void
 InstallOverridenMethod(OverridenMethodFn callback)
 {
 	OverridenMethod = callback;
@@ -1408,12 +1393,6 @@
 }
 
 void
-InstallIsSmokeClass(IsSmokeClassFn callback)
-{
-	IsSmokeClass = callback;
-}
-
-void
 InstallGetProperty(OverridenMethodFn callback)
 {
 	GetProperty = callback;
--- trunk/playground/bindings/kimono/qyoto.h #646049:646050
@@ -71,8 +71,8 @@
 typedef void* (*OverridenMethodFn)(void *, const char *);
 typedef void (*InvokeMethodFn)(void *, void *, void *);
 typedef void* (*CreateInstanceFn)(const char *);
+typedef void* (*GetInstanceFn)(void *, bool);
 typedef void (*InvokeCustomSlotFn)(void*, const char*, void*, void*);
-typedef bool (*IsSmokeClassFn)(void*);
 typedef void (*AddInt)(void*, int);
 typedef void (*AddIntObject)(void*, int, void*);
 typedef void* (*DictToMap)(void*, int);



More information about the Kde-bindings mailing list