[Kde-bindings] Qyoto: SIGNALS/SLOTS

Richard Dale Richard_Dale at tipitina.demon.co.uk
Mon Jan 16 20:31:18 UTC 2006


On Monday 16 January 2006 18:53, Arno Rehn wrote:
> Hi,
>
> as I have absolutely no clue how to get signals and slots working with
> QMetaObjects, I have another idea:
Well, we just need to copy the QtRuby code for constructing them on the fly, 
but derive the signal and slot names via C# reflection. For signals, we look 
at the IQApplicationSignals interface or what ever, and for slots we go 
through the methods via reflection looking for which ones are marked with 
Q_SLOT. Then a Qyoto class which has been subclassed, would return a 
QMetaObject with those extra slots/signals from the QObject.MetaObject() 
method call. Then when there is a qt_invoke() virtual method callback, it 
would need to know if it was calling C# slots or C++ ones. If C#, then it 
does something similar to a virtual method callback. If C++ it just calls the 
qt_invoke() method in the superclass, which would in turn call a C++ slot.

> With the unsafe keyword, the documentation says, we can code normal C in
> C#, so I wondered if we could do something like Qt#'s libqtsharp (yeah, I
> know again it's Qt#...), but dynamically and in the C#-code. Maybe it would
> be possible do create something like a moc but for C#, which creates code
> for each class containing the methods for connecting a signal to a slot...
It isn't any harder to do what I've described above, I'm sorry I haven't 
explained what needs doing very well. 

Here's what I've been doing this weekend, maybe have a look at this code? I 
haven't finished it, but maybe you can help. The reflection call needs to 
obtain this dummy constructor:

	[SmokeClass("QApplication")]
	public class QApplication : QObject, IDisposable {
 		protected QApplication(Type dummy) : base((Type) null) {}
		interface IQApplicationProxy {

So the code below works, but it will get any non-public constructor, rather 
than the one with the specific arg of 'Type dummy'. I couldn't work out how 
to use 'GetConstructor()' for protected constructors:

		// 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
		// dummy constructor which takes a Type as an arg, like this for example:
		//
 		//		protected QWidget(Type dummy) : base((Type) null) {}
		//
		// The constructor is run to create the wrapper instance. Then the method 
		// to create the transparent proxy to forward the method calls to 
		// SmokeInvocation.Invoke() is called. In the case of the QWidget
		// example above, this method would be called 'CreateQWidgetProxy()'.
		static IntPtr CreateInstance(string className) {
			Type klass = Type.GetType(className);

			ConstructorInfo[] constructorInfo = klass.GetConstructors(	
BindingFlags.NonPublic 
																	| BindingFlags.Instance
																	| BindingFlags.DeclaredOnly);

			Type[] constructorParamTypes = new Type[1];
			constructorParamTypes[0] = Type.GetType("System.Type");;
//			ConstructorInfo constructor = 
klass.GetConstructor(constructorParamTypes);
			if (constructorInfo[0] == null) {
				Console.WriteLine("CreateInstance(\"{0}\") constructor method missing 
{1}", className, constructorParamTypes[0]);
				return (IntPtr) 0;
			}
			object result = constructorInfo[0].Invoke(new object [] 
{ constructorParamTypes[0] });
			Console.WriteLine("CreateInstance(\"{0}\") constructed {1}", className, 
result);

			Type[] paramTypes = new Type[0];
			MethodInfo proxyCreator = klass.GetMethod("CreateProxy", 
BindingFlags.NonPublic 
																	| BindingFlags.Instance
																	| BindingFlags.DeclaredOnly);
			if (proxyCreator == null) {
				Console.WriteLine("CreateInstance() proxyCreator method missing");
				return (IntPtr) 0;
			}
			proxyCreator.Invoke(result, null);
			return (IntPtr) GCHandle.Alloc(result);
		}

I'll check in what I have anyway. This will fix the problem of not being able 
to wrap C# instances around C++ instances that have been created within C++, 
rather than via ordinary qyoto C# constructors.

-- Richard



More information about the Kde-bindings mailing list