[Kde-bindings] KDE/kdebindings/csharp

Arno Rehn kde at arnorehn.de
Mon Jul 7 00:42:31 UTC 2008


SVN commit 828931 by arnorehn:

* KimonoPluginFactory: If a class isn't found in the assembly, look
  through all of the classes and pick the first one that implements
  the interface and has a matching constructor.
* Allow to call InitRuntime() multiple times to make sure that every
  binding is initialized.

CCMAIL: kde-bindings at kde.org



 M  +8 -0      kimono/ChangeLog  
 M  +66 -21    kimono/src/kimonopluginfactory.cpp  
 M  +5 -0      qyoto/ChangeLog  
 M  +12 -6     qyoto/src/SmokeInvocation.cs  


--- trunk/KDE/kdebindings/csharp/kimono/ChangeLog #828930:828931
@@ -1,3 +1,11 @@
+2008-07-07  Arno Rehn  <arno at arnorehn.de>
+
+	* KimonoPluginFactory: If a class isn't found in the assembly, look
+	  through all of the classes and pick the first one that implements
+	  the interface and has a matching constructor.
+	* Allow to call InitRuntime() multiple times to make sure that every
+	  binding is initialized.
+
 2008-07-06  Arno Rehn  <arno at arnorehn.de>
 
 	* mono_jit_cleanup() is now called from a function that is registered
--- trunk/KDE/kdebindings/csharp/kimono/src/kimonopluginfactory.cpp #828930:828931
@@ -56,17 +56,17 @@
 private:
 	void initQyotoRuntime();
 	QByteArray camelize(QByteArray name);
+	QList<const char*> assemblyGetClasses(const char* path);
 	
 	QHash<QString, MonoAssembly*> assemblies;
 	QHash<MonoAssembly*, MonoImage*> images;
 	
 	MonoAssembly* qyotoAssembly;
 	MonoImage* qyotoImage;
+	MonoMethod* initRuntimeMethod;
 	
 	QList<MonoObject*> objects;
 	QList<guint32> handles;
-	
-	bool qyotoInitialized;
 };
 K_EXPORT_PLUGIN(KimonoPluginFactory)
 
@@ -82,7 +82,7 @@
 }
 
 KimonoPluginFactory::KimonoPluginFactory()
-	: qyotoAssembly(0), qyotoImage(0), qyotoInitialized(false)
+	: qyotoAssembly(0), qyotoImage(0), initRuntimeMethod(0)
 {
 }
 
@@ -109,22 +109,47 @@
     return camelCaseName;
 }
 
+QList<const char*>
+KimonoPluginFactory::assemblyGetClasses(const char* path)
+{
+	static MonoImage* corlib = mono_get_corlib();
+	static MonoMethodDesc* assemblyLoadFromDesc = mono_method_desc_new("System.Reflection.Assembly:LoadFrom(string)", true);
+	static MonoMethod* assemblyLoadFrom = mono_method_desc_search_in_image(assemblyLoadFromDesc, corlib);
+	
+	void* args[1];
+	args[0] = mono_string_new(domain, path);
+	MonoObject* assembly = mono_runtime_invoke(assemblyLoadFrom, NULL, args, NULL);
+	
+	static MonoMethodDesc* assemblyGetTypesDesc = mono_method_desc_new("System.Reflection.Assembly:GetTypes()", true);
+	static MonoMethod* assemblyGetTypes = mono_method_desc_search_in_image(assemblyGetTypesDesc, corlib);
+	
+	MonoArray* types = (MonoArray*) mono_runtime_invoke(assemblyGetTypes, assembly, NULL, NULL);
+	
+	static MonoClass* type = mono_class_from_name(corlib, "System", "MonoType");
+	static MonoProperty* typeFullName = mono_class_get_property_from_name(type, "FullName");
+	
+	QList<const char*> ret;
+	for (int i = 0; i < mono_array_length(types); i++) {
+		MonoObject* obj = mono_array_get(types, MonoObject*, i);
+		ret << mono_string_to_utf8((MonoString*) mono_property_get_value(typeFullName, obj, NULL, NULL));
+	}
+	
+	return ret;
+}
+
 void
 KimonoPluginFactory::initQyotoRuntime()
 {
-	if (qyotoInitialized)
-		return;
-
 	// open the assembly 'qt-dotnet', look for Qyoto.SmokeInvocation.InitRuntime() and call it
 	// it seems that there's now way to call static c'tors explicitly, hence the extra method
-	qyotoAssembly = mono_domain_assembly_open(domain, "qt-dotnet");
-	qyotoImage = mono_assembly_get_image(qyotoAssembly);
-	MonoMethodDesc* desc = mono_method_desc_new("Qyoto.SmokeInvocation:InitRuntime()", true);
-	MonoClass* klass = mono_class_from_name(qyotoImage, "Qyoto", "SmokeInvocation");
-	MonoMethod* meth = mono_method_desc_search_in_class(desc, klass);
-	mono_runtime_invoke(meth, NULL, NULL, NULL);
-	
-	qyotoInitialized = true;
+	if (!initRuntimeMethod) {
+		qyotoAssembly = mono_domain_assembly_open(domain, "qt-dotnet");
+		qyotoImage = mono_assembly_get_image(qyotoAssembly);
+		MonoMethodDesc* desc = mono_method_desc_new("Qyoto.SmokeInvocation:InitRuntime()", true);
+		MonoClass* klass = mono_class_from_name(qyotoImage, "Qyoto", "SmokeInvocation");
+		initRuntimeMethod = mono_method_desc_search_in_class(desc, klass);
+	}
+	mono_runtime_invoke(initRuntimeMethod, NULL, NULL, NULL);
 }
 
 QObject*
@@ -176,14 +201,34 @@
 	QString className = camelize(file.completeBaseName().toLatin1());
 	MonoClass* klass = mono_class_from_name(image, (const char*) nameSpace.toLatin1(), (const char*) className.toLatin1());
 
-	// we want the Foo.Bar:.ctor(QObject, List<QVariant>)
-	QString methodName = nameSpace + "." + className + ":.ctor(Qyoto.QObject,System.Collections.Generic.List`1)";
-	MonoMethodDesc* desc = mono_method_desc_new((const char*) methodName.toLatin1(), true);
-	
-	MonoMethod* ctor = mono_method_desc_search_in_class(desc, klass);
-	
+	MonoMethod* ctor = 0;
+	if (klass) {
+		// we want the Foo.Bar:.ctor(QObject, List<QVariant>)
+		QString methodName = nameSpace + "." + className + ":.ctor(Qyoto.QObject,System.Collections.Generic.List`1)";
+		MonoMethodDesc* desc = mono_method_desc_new((const char*) methodName.toLatin1(), true);
+		ctor = mono_method_desc_search_in_class(desc, klass);
+	} else {
+		QString ifacestr(iface);
+		ifacestr.replace("::", ".");
+		foreach(QString name, assemblyGetClasses((const char*) path.toLatin1())) {
+			nameSpace = name.left(name.lastIndexOf("."));
+			className = name.right(name.size() - name.lastIndexOf(".") - 1);
+			klass = mono_class_from_name(image, (const char*) nameSpace.toLatin1(), (const char*) className.toLatin1());
+			MonoClass* p = klass;
+			do {
+				if (ifacestr != mono_type_get_name(mono_class_get_type(p)))
+					continue;
+				QString methodName = nameSpace + "." + className + ":.ctor(Qyoto.QObject,System.Collections.Generic.List`1)";
+				MonoMethodDesc* desc = mono_method_desc_new((const char*) methodName.toLatin1(), true);
+				ctor = mono_method_desc_search_in_class(desc, klass);
+				if (ctor) break;
+			} while ((p = mono_class_get_parent(p)));
+			if (ctor) break;
+		}
+	}
+
 	if (!ctor) {
-		kWarning() << "Didn't find method" << methodName << "in class" << nameSpace + "." + className;
+		kWarning() << "Didn't find a matching constructor in the classes of the assembly";
 		return 0;
 	}
 	
--- trunk/KDE/kdebindings/csharp/qyoto/ChangeLog #828930:828931
@@ -1,3 +1,8 @@
+2008-07-07  Arno Rehn  <arno at arnorehn.de>
+
+	* Allow to call InitRuntime() multiple times to make sure every binding
+	  is initialized.
+
 2008-07-06  Richard Dale  <richard.j.dale at gmail.com>
 
 	* Where multiple inheritance was catered for in the Qyoto bindings each
--- trunk/KDE/kdebindings/csharp/qyoto/src/SmokeInvocation.cs #828930:828931
@@ -425,19 +425,25 @@
 		}
 
 		static bool runtimeInitialized = false;
+		static List<Assembly> initializedAssemblies = new List<Assembly>();
 
 		public static void InitRuntime() {
-			if (runtimeInitialized)
-				return;
-			Qyoto.Init_qyoto();
-			SmokeMarshallers.SetUp();
+			if (!runtimeInitialized) {
+				Qyoto.Init_qyoto();
+				SmokeMarshallers.SetUp();
+				runtimeInitialized = true;
+			}
 			
 			// initialize other referenced smoke bindings
 			foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies()) {
+				if (initializedAssemblies.Contains(a)) return;
 				AssemblySmokeInitializer attr = (AssemblySmokeInitializer) Attribute.GetCustomAttribute(a, typeof(AssemblySmokeInitializer));
-				if (attr != null) attr.CallInitSmoke();
+				if (attr != null) {
+					Console.WriteLine("Init {0}", a);
+					attr.CallInitSmoke();
+				}
+				initializedAssemblies.Add(a);
 			}
-			runtimeInitialized = true;
 		}
 
 		static SmokeInvocation() {



More information about the Kde-bindings mailing list