[Kde-bindings] Qyoto Custom Signal Arguments

Richard Dale rdale at foton.es
Wed Sep 6 09:37:39 UTC 2006


On Tuesday 05 September 2006 20:46, Arno Rehn wrote:
> Am Montag, 4. September 2006 13:49 schrieb Richard Dale:
> > On Sunday 03 September 2006 18:17, Arno Rehn wrote:
> > > > Ruby program attached.
> > > > Why isn't emitSignal() called?
> > >
> > > Oh sorry, I forgot about
> > > "but you can't emit existing c++ signals in QtRuby like you can in
> > > Qyoto, only ruby signals."
> > > Sorry again. Then I'll have to declare my own signals.
> >
> > Yes, just redeclare the signal in the MySlider class like this, and it
> > should work ok:
> >
> > class MySlider < Qt::Slider
> >         signals 'valueChanged(int)'
> >
> > 	def initialize(parent)
> > 		super(parent)
> > 	end
> >
> > 	def Emit()
> > 		emit(valueChanged(5))
> > 	end
> > end
>
> Now, to get back to the topic: I didn't get any step further till now. But
> there is a thing that confuses me:
> The constructor of EmitSignal is:
>
>     EmitSignal(QObject *qobj, int id, int items, MocArgument * args,
> Smoke::StackItem *sp) :
>     _qobj(qobj), _id(id), _sp(sp), _items(items), _args(args),
>     _cur(-1), _called(false)
>     {
> 	_stack = new Smoke::StackItem[_items];
>     }
>
> Here we create a new pointer to a Array of StackItem-Structures. As far as
> I know, the structures shouldn't contain any values by now. But later we
> use the array again, without filling it with any values:
>
>     Smoke::StackItem *si = _stack + i;
>     switch(_args[i].argType) {
>     case xmoc_bool:
>       o[i + 1] = &si->s_bool;
>       break;
>     case xmoc_int:
>       o[i + 1] = &si->s_int;
>       break;
>
> I've seen this many times in qtruby, too. Now my question is, where do the
> values come from?

void
SigSlotBase::next() 
{
	int oldcur = _cur;
	_cur++;

	while(!_called && _cur < _items - 1) {
		Marshall::HandlerFn fn = getMarshallFn(type());
		(*fn)(this);
		_cur++;
	}

	mainfunction();
	_cur = oldcur;
}

It's driven by the call to EmitSignal::next(). For each argument, the loop 
above calls a pointer to a function looked up from the table 'Qt_handlers' in 
handlers.cpp, and that function marshalls from the Ruby (or C#) value to the 
Smoke::Stack which is an array of void *'s. 

Then in the mainfunction() method it calls emitSignal(), which in turn calls 
the C function smokeStackToQtStack() which copies the values from the Smoke 
stack of void *'s to the very similar stack of void *'s that Qt itself uses.

void 
EmitSignal::emitSignal() 
{
	if (_called) return;
	_called = true;
	void ** o = new void*[_items];
	smokeStackToQtStack(_stack, o + 1, _items - 1, _args + 1);
	_obj->metaObject()->activate(_obj, _id, o);
	
	if (_args[0].argType != xmoc_void) {
		SignalReturnValue r(o, _result, _args);
	}
	delete[] o;
}

void 
EmitSignal::mainfunction() 
{ 
	emitSignal(); 
}

The way the marshaller functions call back into the main EmitSignal instance 
is quite clever and it took me a while to fully understand how it works, and 
there is a bit more to it than I've explained above. But that should be 
enough to see how the Smoke::Stack array is set up.

-- Richard





More information about the Kde-bindings mailing list