[Kde-bindings] Qyoto: SIGNALS/SLOTS

Richard Dale Richard_Dale at tipitina.demon.co.uk
Fri Dec 9 19:16:05 UTC 2005


On Friday 09 December 2005 16:47, Arno Rehn wrote:
> Am Donnerstag, 8. Dezember 2005 21:58 schrieb Richard Dale:
> > On Thursday 08 December 2005 19:32, Arno Rehn wrote:
> > > Am Mittwoch, 7. Dezember 2005 17:43 schrieb Richard Dale:
> > > > On Wednesday 07 December 2005 15:36, Arno Rehn wrote:
> > > > > Hi,
> > > > >
> > > > > I experimented a bit and created a more complex Hello-World sample
> > > > > app. I wanted to connect the "clicked()" signal of a button to the
> > > > > "quit()" slot of QApplication. Got a SIGSEGV.
> > > > > I looked into the Qt.cpp of qtruby and it seems as signals and
> > > > > slots are a bit difficult.
> > > >
> > > > QtRuby dynamically constructs QMetaObjects, rather than it being done
> > > > at compile time by the moc pre-processor. But the actual runtime is
> > > > identical. We need a way of denoting which methods are slots in C#,
> > > > and I assume we can use 'attributes' (or are they called
> > > > 'annotations' I've forgotten). Maybe you could have a look at how we
> > > > might mark slots, and then the runtime side should be very similar to
> > > > QtRuby. We don't have to invent anything much new apart from that.
> > >
> > > OK, I found out how to mark Signals/Slots with Attributes. I attached
> > > an example.
> >
> > That looks good. In Qt4 there is a macro 'Q_SLOTS' to use instead of the
> > 'slots' moc keyword because of a clash with the Boost library. So maybe
> > slots could be marked like this, to look more like that macro:
> >
> > 	[Q_SLOT()]
> > 	public void mySlot()
> > 	{
> > 	}
> >
> > Maybe signals need to map onto delegates, rather than ordinary methods.
>
> Would be a good idea. Maybe signals need to be delegates, which are set by
> the programmer or  'QObject.Connect()'. Could look like this:
>
> 	public class QApplication : ...
> 	{
> 		delegate void LastWindowClosedHandler();
>
> 		[Q_SIGNAL()]
> 		LastWindowClosedHandler LastWindowClosed;
>
> 		...
> 	}
Yes, and I think it would need to have a string with the C++ type signature, 
like the Q_SLOT example I give below:

 		[Q_SIGNAL("void lastWindowClosed()")]
 		LastWindowClosedHandler LastWindowClosed;

> Now we could just say 'LastWindowClosed' is set by the programmer. This
> would keep the delegate-system of Mono/.NET. Additionally it would be
> possible to create a 'QObject.Connect(...)' which dynamically connects
> 'LastWindowClosed' to another method. But I don't know how to check whether
> the underlying C++-instance triggered the signal. Then it would be quite
> easy to call the appropiate delegate.
We don't want to dynamically connect the delegate to target slots because the 
Qt runtime will do that. But we would need to trap the LastWindowClosed 
delegate call and then raise the Qt signal inside the Qyoto runtime. I need 
to read up more on how delegates work. Should the Q_SIGNAL attribute be 
against the delegate declaration?

		[Q_SIGNAL("void lastWindowClosed()")] 
 		delegate void LastWindowClosedHandler();

> > At the moment an interface is generated containing the type signatures of
> > signals like this:
> >
> > 	public interface IQApplicationSignals {
> > 		void LastWindowClosed();
> > 		void AboutToQuit();
> > 		void GuiThreadAwake();
> > 	}
> >
> > And I was thinking of having a QObject.Emit() method which returned a
> > transparent proxy, so you could invoke a signal with like this:
> >
> > (LastWindowClosed) myInstance.Emit()
I got this wrong, it should look like this:

((IQApplicationSignals) myInstance.Emit()).LastWindowClosed();

And the interface for a class would need to extend the signals interface for 
its superclass. So in the case above the IQApplicationSignals interface would 
need to extend the IQObjectSignals interface. But this doesn't really fit in 
with delegates.

> > And it would be forwarded to SignalInvocation.Invoke(), in a similar
> > manner to how ordinary method calls get diverted to
> > SmokeInvocation.Invoke() at the moment.
> >
> > But slots are easiest to get working first though, and marking them with
> > attributes like you've done looks pretty good to me.
I think the slots need to be marked as slots, along with the C++ type 
signature that would be used for constructing the QMetaObject entry for it. 
Like this:

using System;
using System.Reflection;

[AttributeUsage( AttributeTargets.Method )]
class Q_SLOT : Attribute
{
	public string signature;

	public string Signature
	{
		get
		{
			return signature;
		}
	}

	public Q_SLOT(string signature)
	{
		this.signature = signature;
	}
}

public class main : Object
{
	public static void Main(string[] args)
	{
		new main();
	}
	
	public main()
	{
		MethodInfo miSlot = this.GetType().GetMethod( "mySlot" );
		Console.WriteLine( GetAttributeName( miSlot ) );

		object[] attributes;
		attributes = miSlot.GetCustomAttributes(typeof(Q_SLOT), false);
		if (attributes.Length > 0) {
			Q_SLOT slotAttr = (Q_SLOT) attributes[0];
			Console.WriteLine( "Q_SLOT signature: {0}", slotAttr.Signature );
		}
		
	}
	
	[Q_SLOT("void mySlot(QString)")]
	public void mySlot(string arg)
	{
	}
	
	public string GetAttributeName( MethodInfo mi )
	{
		Attribute[] attr = ( Attribute[] ) mi.GetCustomAttributes( true );
		
		if( attr.Length < 1 )
			return null;
		
		Type t = attr[0].GetType();
		return t.Name;
	}
}

-- Richard



More information about the Kde-bindings mailing list