kde-bindings@kde.org
[Top] [All Lists]

playground/bindings/kimono

Subject: playground/bindings/kimono
From: Richard Dale
Date: Fri, 23 Mar 2007 12:17:54 +0000
SVN commit 645696 by rdale:

* Cache various items in a dictionary with a key of the Smoke class's
  type to avoid using reflection to look up the items each time. A timing
  test consisting of starting the t14 cannon game and firing 5 shots at
  force 40, used half the mill of the version without caching.

* The following class is used to cache the data:

        public class SmokeClassData {
                public string className;
                public ConstructorInfo constructorInfo;
                public object[] constructorParamTypes;
                public MethodInfo proxyCreator;
                public FieldInfo smokeObjectField;
        }

        - classname: the C++ signature of the Smoke class
        - constructorInfo: the ConstructorInfo to construct a new instance
        - constructorParamTypes: the argument to pass to the constructorInfo
        - proxyCreator: the method to create the transparent proxy for the 
                new instance
        - smokeObjectField: the field for holding a pointer to the 
                smokeqyoto_object struct for the instance

* Add an entry to the strong reference map for custom QWidget subclasses 
  to prevent them being GC'd prematurally.

CCMAIL: kde-bindings@xxxxxxx



 M  +28 -0     ChangeLog  
 M  +61 -39    SmokeMarshallers.cs  
 M  +4 -0      handlers.cpp  
 M  +11 -3     qyoto.cpp  


--- trunk/playground/bindings/kimono/ChangeLog #645695:645696
@@ -1,3 +1,31 @@
+2007-03-23  Richard Dale  <rdale@xxxxxxxx>
+
+       * Cache various items in a dictionary with a key of the Smoke class's
+         type to avoid using reflection to look up the items each time. A 
timing
+         test consisting of starting the t14 cannon game and firing 5 shots at
+         force 40, used half the mill of the version without caching.
+
+       * The following class is used to cache the data:
+
+               public class SmokeClassData {
+                       public string className;
+                       public ConstructorInfo constructorInfo;
+                       public object[] constructorParamTypes;
+                       public MethodInfo proxyCreator;
+                       public FieldInfo smokeObjectField;
+               }
+
+               - classname: the C++ signature of the Smoke class
+               - constructorInfo: the ConstructorInfo to construct a new 
instance
+               - constructorParamTypes: the argument to pass to the 
constructorInfo
+               - proxyCreator: the method to create the transparent proxy for 
the 
+                       new instance
+               - smokeObjectField: the field for holding a pointer to the 
+                       smokeqyoto_object struct for the instance
+
+       * Add an entry to the strong reference map for custom QWidget 
subclasses 
+         to prevent them being GC'd prematurally.
+
 2007-03-22  Richard Dale  <rdale@xxxxxxxx>
 
        * Added debug methods for logging GCHandle.Alloc() and Free() calls
--- trunk/playground/bindings/kimono/SmokeMarshallers.cs #645695:645696
@@ -25,6 +25,14 @@
        using System.Runtime.InteropServices;
        using System.Text;
 
+       public class SmokeClassData {
+               public string className;
+               public ConstructorInfo constructorInfo;
+               public object[] constructorParamTypes;
+               public MethodInfo proxyCreator;
+               public FieldInfo smokeObjectField;
+       }
+
        public class SmokeMarshallers : object {
                
 #region C++ functions
@@ -192,7 +200,6 @@
                }
                
                public static IntPtr GetSmokeObject(IntPtr instancePtr) {
-
                        if (((int) instancePtr) == 0) {
                                return (IntPtr) 0;
                        }
@@ -200,22 +207,16 @@
                        Object instance = ((GCHandle) instancePtr).Target;
                        Debug.Assert(instance != null);
 
-                       FieldInfo fieldInfo = instance.GetType().GetField(      
"smokeObject", 
-                                                                               
                                        BindingFlags.NonPublic 
-                                                                               
                                        | BindingFlags.GetField
-                                                                               
                                        | BindingFlags.Instance );
-                       return (IntPtr) fieldInfo.GetValue(instance);
+                       SmokeClassData data = 
GetSmokeClassData(instance.GetType());
+                       return (IntPtr) 
data.smokeObjectField.GetValue(instance);
                }
                
                public static void SetSmokeObject(IntPtr instancePtr, IntPtr 
smokeObjectPtr) {
                        Object instance = ((GCHandle) instancePtr).Target;
                        Debug.Assert(instance != null);
 
-                       FieldInfo fieldInfo = instance.GetType().GetField(      
"smokeObject", 
-                                                                               
                                        BindingFlags.NonPublic 
-                                                                               
                                        | BindingFlags.GetField
-                                                                               
                                        | BindingFlags.Instance );
-                       fieldInfo.SetValue(instance, smokeObjectPtr);
+                       SmokeClassData data = 
GetSmokeClassData(instance.GetType());
+                       data.smokeObjectField.SetValue(instance, 
smokeObjectPtr);
                        return;
                }
                
@@ -356,6 +357,50 @@
                        }
                }
 
+               static Dictionary<Type, SmokeClassData> smokeClassCache = new 
Dictionary<Type, SmokeClassData> ();
+               
+               public static SmokeClassData GetSmokeClassData(Type t) {
+                       SmokeClassData result;
+
+                       if (!smokeClassCache.TryGetValue(t, out result)) {
+                               result = new SmokeClassData();
+
+                               object[] attr = 
t.GetCustomAttributes(typeof(SmokeClass), false);
+                               if (attr.Length > 0) {
+                                       result.className = ((SmokeClass) 
attr[0]).signature;
+                               }
+
+                               Type[] paramTypes = new Type[1];
+                               paramTypes[0] = typeof(Type);
+                               result.constructorParamTypes = new object[] { 
paramTypes[0] };
+
+                               result.constructorInfo = 
t.GetConstructor(BindingFlags.NonPublic 
+                                       | BindingFlags.Instance, null, new 
Type[ ] { typeof( Type ) } , null);
+                               Debug.Assert(   result.constructorInfo != null,
+                                                               
"GetSmokeClassData(\"" + result.className + "\") constructor method missing" );
+
+                               Type klass = t;
+                               do {
+                                       result.proxyCreator = 
klass.GetMethod("CreateProxy", BindingFlags.NonPublic 
+                                                                               
                                                | BindingFlags.Instance
+                                                                               
                                                | BindingFlags.DeclaredOnly);
+
+                                       klass = klass.BaseType;
+                               } while (result.proxyCreator == null && klass 
!= typeof(object));
+
+                               Debug.Assert(   result.proxyCreator != null, 
+                                                               
"GetSmokeClassData(\"" + result.className + "\") no CreateProxy() found" );
+
+                               result.smokeObjectField = t.GetField(   
"smokeObject", 
+                                                                               
                                BindingFlags.NonPublic 
+                                                                               
                                | BindingFlags.GetField
+                                                                               
                                | BindingFlags.Instance );
+                               smokeClassCache[t] = result;
+                       }
+
+                       return result;
+               }
+
                // 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
@@ -367,42 +412,19 @@
                // 'CreateProxy()' to create the transparent proxy to forward 
the method
                // calls to SmokeInvocation.Invoke() is called.
                public static IntPtr CreateInstance(string className) {
-                       Type klass = Type.GetType(className);
-                       Type[] constructorParamTypes = new Type[1];
-                       constructorParamTypes[0] = typeof(Type);
-                       ConstructorInfo constructorInfo = 
klass.GetConstructor(BindingFlags.NonPublic 
-                                       | BindingFlags.Instance, null, new 
Type[ ] { typeof( Type ) } , null);
-
-                       Debug.Assert(   constructorInfo != null,
-                                                       "CreateInstance(\"" + 
className + "\") constructor method missing" );
-
-                       object result = constructorInfo.Invoke(new object [] { 
constructorParamTypes[0] });
+                       SmokeClassData data = 
GetSmokeClassData(Type.GetType(className));
+                       object result = 
data.constructorInfo.Invoke(data.constructorParamTypes);
 #if DEBUG
                        if ((QDebug.DebugChannel() & QtDebugChannel.QTDB_GC) != 
0) {
                                Console.WriteLine("CreateInstance(\"{0}\") 
constructed {1}", className, result);
                        }
 #endif
-
-                       MethodInfo proxyCreator = null;
-                       do {
-                               proxyCreator = klass.GetMethod("CreateProxy", 
BindingFlags.NonPublic 
-                                                                               
                                                | BindingFlags.Instance
-                                                                               
                                                | BindingFlags.DeclaredOnly);
-                               if (proxyCreator != null) {
-                                       proxyCreator.Invoke(result, null);
+                       data.proxyCreator.Invoke(result, null);
 #if DEBUG
-                                       return (IntPtr) 
DebugGCHandle.Alloc(result);
+                       return (IntPtr) DebugGCHandle.Alloc(result);
 #else
-                                       return (IntPtr) GCHandle.Alloc(result);
+                       return (IntPtr) GCHandle.Alloc(result);
 #endif
-                               }
-
-                               klass = klass.BaseType;
-                       } while (klass != typeof(object));
-
-                       Debug.Assert(   proxyCreator != null, 
-                                                       "CreateInstance(\"" + 
className + "\") no CreateProxy() found" );
-                       return (IntPtr) 0;
                }
 
                public static IntPtr IntPtrToCharStarStar(IntPtr ptr) {
--- trunk/playground/bindings/kimono/handlers.cpp #645695:645696
@@ -257,6 +257,10 @@
                if (qwidget->parentWidget() != 0) {
                        return true;
                }
+               // Don't garbage collect custom subclasses of QWidget classes 
for now
+               const QMetaObject * meta = qwidget->metaObject();
+               Smoke::Index classId = o->smoke->idClass(meta->className());
+               return (classId == 0);
        } else if (isDerivedFromByName(o->smoke, className, "QObject")) {
                QObject * qobject = (QObject *) o->smoke->cast(o->ptr, 
o->classId, o->smoke->idClass("QObject"));
                if (qobject->parent() != 0) {
--- trunk/playground/bindings/kimono/qyoto.cpp #645695:645696
@@ -998,9 +998,18 @@
                }
 
                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) {
+               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);
                        }
@@ -1015,8 +1024,7 @@
                        
                        args[0].s_int = qt_metacall(obj, _c, _id, _o);
 
-                       // This line stops custom slots from working - how can 
that be?
-//                     (*FreeGCHandle)(obj);
+                       (*FreeGCHandle)(obj);
                        return true;
                }
                

<Prev in Thread] Current Thread [Next in Thread>