[Kde-bindings] playground/bindings/kimono
Richard Dale
Richard_Dale at tipitina.demon.co.uk
Fri Mar 23 12:17:54 UTC 2007
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 at kde.org
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 at foton.es>
+
+ * 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 at foton.es>
* 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;
}
More information about the Kde-bindings
mailing list