[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