Discussion:
Dynamic binding -- Qt's Signals and Slots vs Objective-C
(too old to reply)
Bill Baxter
2006-09-21 17:10:56 UTC
Permalink
There seems to be a lot in common between Qt's signals and slots (Qt
S&S) and Objective-C's messaging system. Both basically offer a way to
call a method using a string rather than a pointer, i.e they allow
run-time binding and dispatch. Both seem to be considered Really Good
Things by those who use them, primarily for the purpose of creating GUIs.

So is there anyone out there knowledgeable about both who could compare
and contrast? This link from Fredrik, http://tinyurl.com/kojmm, helped
me understand Obj-C a little, but I've got more questions:

- Is Qt S&S a subset of Obj-C's messaging?
- Could Qt S&S be implemented using Obj-C messaging?
- Could Obj-C-like messaging be implemented using Qt S&S?
- Qt S&S includes an observer pattern in that emit() will call all
connected slots. Is this built into Obj-C messaging too?
- Qt requires derivation from QObject to participate in S&S. Does Obj-C
also require deriving from a particular base object? Is it explicit?
- What is the overhead to support Obj-C messaging in a class? Is there
a way to create an Obj-C class that doesn't support messaging?
- Do people use Obj-C messaging for anything besides GUIs?

The goal of this questioning, of course, is to encourage discussion
about whether these or any other form dynamic binding could / should be
added to D.

I've heard many people in C++ land say things to the effect of "Bah,
those silly Qt people weren't smart enough realize that you can
implement signals and slots directly in C++". But I've not been
particularly impressed by the pure C++ S&S libraries I've seen. On the
other hand, I found Qt's S&S to be simple, clean, straightforward, and
very easy to use. And I've not heard anything but praise about making
GUIs with Obj-C. Lutger's S&S for D posted earlier looks very nice, but
there must be something neat that Qt S&S--being dynamic--can do that
isn't possible with the static S&S solutions. Like enumerating
available signals for use in a GUI builder tool.

- Is it possible to mix D-style classes with Obj-C style messaging?
Apple's Objective-C++ apparently doesn't allow it.
http://developer.apple.com/releasenotes/Cocoa/Objective-C++.html
I.e. a class is either a C++ class or an Obj-C class. They can call
each other, but they are separate. You can't send an Obj-C message to a
C++ class. I think the ideal, though, would be something closer to Qt
where you have the ability to make any method you want be a slot. In Qt
those methods remain valid C++ methods, but you can also call them by
name, effectively.

I think what it comes down to is that you want to have as many tools
available as possible in your toolbox. Some things are just easier to
do dynamically (for flexibility and loose coupling), and other things
are better done statically (for runtime speed and robust compile-time
type-checking). I think that explains the growing popularity of hybrids
like Jython and JRuby. C# probably fits in there somewhere too.

--bb
Fredrik Olsson
2006-09-25 17:43:44 UTC
Permalink
First some rech stuff :).

How Qt S&S does it:

Each object can have signals and slots. A signal is an event that can be
signaled to the "runtime", and a slot is a method that is performed in
response to a signal.

You connect signals and slots like this:
connect(&obj1, SIGNAL(valueChanged(int)), &obj2, SLOT(setValue(int)));
You are free to hook up a signal to as many slots as you like, and to
different objects.

And you may then later emit this signal (From obj1) using:
emit valueChanged(42);
which will cause the setValue(int) slot to be performed.


How Obj-C Cocoa does it:

Each object can have an action and a target. An action is an event that
is signaled at run-time, and the target is an object instance to call.
If target is nil (null) then the action will be sent to the responder
chain, instead of a predestined object.

The responder chain is implemented in the NSResponder protocol
(Interface) and will send the action down the controllers is logical
order acording to how windows are stacked, ending up in the
NSApplication instance if no one else is interested. This make sure that
if a single menu item (OSX == one menu you know :) ) has nil as target,
then the topmost window will get a chance to respond first, and yet the
same item will work for all windows.

You connect an action/target like this:
[obj1 setAction:@selector(valueChanged:)];
[obj1 setTarget:obj2];

And you can later "emit" the action using:
[obj1 sendAction:[obj1 action] to:[obj1 target]];
which will cause the valueChanged: method of obj2 to be performed. In
reality most classes have shortcuts such as sendAction, and even more so
you rarely need to care about sending manually at all.


Bill Baxter skrev:
<sbip>
Post by Bill Baxter
- Is Qt S&S a subset of Obj-C's messaging?
I think Qt's S&S is more of a superset. Qt allows a signal to trigger
many slots, while Obj-C have only one target. In short, one button click
invokes a single action, in Obj-C, while in Qt it could invoke a series
of actions.

This is more of a design limitation in Cocoa, not in Objective-C.

On the plus-side of Cocoa is that a "signal"/"action" do not need to
have a target set, but can dynamically find it's target using a
responder chain, for example targetting the top-most windows document
controller from a single menu item.
Post by Bill Baxter
- Could Qt S&S be implemented using Obj-C messaging?
Yes, no problem. And no hacks :).
Post by Bill Baxter
- Could Obj-C-like messaging be implemented using Qt S&S?
Yes, with some problem. The responder chain mechanism needs to be
implemented.
Post by Bill Baxter
- Qt S&S includes an observer pattern in that emit() will call all
connected slots. Is this built into Obj-C messaging too?
As I mentioned Cocoa only use one action. So the equivalent of emit()
would be performAction. But it can only be hooked up to a single
target/slot.
Post by Bill Baxter
- Qt requires derivation from QObject to participate in S&S. Does Obj-C
also require deriving from a particular base object? Is it explicit?
More or less. All existing senders are subclasses of NSControl, so using
those subclasses will let you use say [foo sendAction], and such shorter
things. In the same way subclasses of NSResponder will automatically fit
in the responder chain.

But in practice, Obj-C will not care as much of the classes, but of what
the classes implement. So if you send the action foo: to bar what the
run-time will do is a:
if ([bar respondsToSelector:@selector(foo:)]) {
[bar performSelector:@selector(foo:)];
}
And yes, if it does not respond, it is no error, unless you want it to
be, it is perfctly legal to call methods that are not implemented :).
Post by Bill Baxter
- What is the overhead to support Obj-C messaging in a class? Is there
a way to create an Obj-C class that doesn't support messaging?
The Obj-C language is build upon this message dispatch, so no way around
it, each "method call" is a message dispatch. And there is a overhead as
compared to C++. The run-time uses caching and other neat tricks, so in
practice a Obj-C method call cost about 2.5 C++ method calls.
Post by Bill Baxter
- Do people use Obj-C messaging for anything besides GUIs?
Oooh, yes. The real power here is in the dynamic dispatching of
messages. Best of all is what is called categories. You can extend a
class by subclassing, or by adding a category.

NSArray is a base class for static arrays.
NSMutableArray is a subclass of NSArray that is mutable (dynamic).
If you wanted to add a method say something useful as reversedArray to
them, then in C++ (And D) you would need to make two subclasses, one to
NSArray, and one to NSMutableArray, and it would be dead on impossible
make a function accept both without typecasting (Ok, add an interface
then). In Obj-C you can instead add a category to NSArray, and it will
automatically be added to all subclasses as well. Like this:
@interface NSArray (ReversedCat)
- (NSArray *)reversedArray;
@end

And named arguments rocks, for code readability:
myFoo.write("bar.txt", true);
vs
[myFoo writeToFile:@"bar.txt" atomically:YES];

Same thing cn be done with lots of comments, but is rarely done. And
short names have already become a bad habit/convention anyway.
Post by Bill Baxter
The goal of this questioning, of course, is to encourage discussion
about whether these or any other form dynamic binding could / should be
added to D.
Could: YES! The first Obj-C compilers where simple preprocessors for C.
I see no real problem in linking with the GNU Obj-C runtime. And Obj-C
as such is very tiny, the power lies in the flexibility of the little
there is.

Should: Not too sure. I would like it, my only problem with Obj-C is the
C part, so replacing that with D would be nice. But I seriously doubt it
is worth the trouble, mostly because it is a quite different paradigm,
and before you understand it you cannot appreciate it.
Post by Bill Baxter
I've heard many people in C++ land say things to the effect of "Bah,
those silly Qt people weren't smart enough realize that you can
implement signals and slots directly in C++". But I've not been
particularly impressed by the pure C++ S&S libraries I've seen. On the
other hand, I found Qt's S&S to be simple, clean, straightforward, and
very easy to use. And I've not heard anything but praise about making
GUIs with Obj-C. Lutger's S&S for D posted earlier looks very nice, but
there must be something neat that Qt S&S--being dynamic--can do that
isn't possible with the static S&S solutions. Like enumerating
available signals for use in a GUI builder tool.
- Is it possible to mix D-style classes with Obj-C style messaging?
Apple's Objective-C++ apparently doesn't allow it.
http://developer.apple.com/releasenotes/Cocoa/Objective-C++.html
I.e. a class is either a C++ class or an Obj-C class. They can call
each other, but they are separate. You can't send an Obj-C message to a
C++ class. I think the ideal, though, would be something closer to Qt
where you have the ability to make any method you want be a slot. In Qt
those methods remain valid C++ methods, but you can also call them by
name, effectively.
This is because C++/D and Obj-C works very differently. Lets call the
object that will have a method called the reciever.

What C++/D does is very simply put: classes are structs with hidden
function pointers, when calling a method it looks up the function
pointer at a static offset from the reciever, and jumps. And the class
better make sure there is a valid function at the other end.

What Obj-C does is that it takes the reciever, and requested method
message and send to objc_msgSend(), that function looks up the correct
function pointer for the given reciever and method pair, if found it
jumps there. If not found it can raise en exception, pass control to a
"unhandled message" method, or silently ignore.


Oh well, hopefully you have less question now at least :).


// Fredrik Olsson
Bill Baxter
2006-09-26 21:49:53 UTC
Permalink
Fredrik,
Thanks for this very informative reply.
It definitely seems from your explanations that just going for "Qt-style
signals and slots" in D is "aiming low", and that a basic dynamic
messaging system is more the level of abstraction you'd want. And from
there you can implement Qt-style S&S easily, as you demonstrated.

However, I think taking a 2.5x speed hit (worse for a poorly optimized
implementation) for all method calls will be difficult for D users to
swallow.

It sounds like basically what is required in terms of per-class storage
is a second sort of vtable per class, a dynamic vtable. Maybe more like
a dictionary/hash-table, but anyway you need some place to store
per-class mappings from messages to actual functions. It could probably
be pointed to from the regular vtable in some manner so that each class
instance still only has the overhead of one vtable pointer.

You can go ahead and put every method in the dynamic dispatch vtable.
It's just per-class, so not a huge overhead. Kind of like how every
non-private method in D is virtual. Then I guess it needs to be the
caller's choice whether to use dynamic dispatch or static. So a
separate syntax for making "message"-based calls, like Objective C uses.

Gotta go, but I think some sort of built-in dynamic dispatch mechanism
like this would have to be part of my "dream language".

--bb
Post by Fredrik Olsson
First some rech stuff :).
Each object can have signals and slots. A signal is an event that can be
signaled to the "runtime", and a slot is a method that is performed in
response to a signal.
connect(&obj1, SIGNAL(valueChanged(int)), &obj2, SLOT(setValue(int)));
You are free to hook up a signal to as many slots as you like, and to
different objects.
emit valueChanged(42);
which will cause the setValue(int) slot to be performed.
Each object can have an action and a target. An action is an event that
is signaled at run-time, and the target is an object instance to call.
If target is nil (null) then the action will be sent to the responder
chain, instead of a predestined object.
The responder chain is implemented in the NSResponder protocol
(Interface) and will send the action down the controllers is logical
order acording to how windows are stacked, ending up in the
NSApplication instance if no one else is interested. This make sure that
if a single menu item (OSX == one menu you know :) ) has nil as target,
then the topmost window will get a chance to respond first, and yet the
same item will work for all windows.
[obj1 setTarget:obj2];
[obj1 sendAction:[obj1 action] to:[obj1 target]];
which will cause the valueChanged: method of obj2 to be performed. In
reality most classes have shortcuts such as sendAction, and even more so
you rarely need to care about sending manually at all.
<sbip>
Post by Bill Baxter
- Is Qt S&S a subset of Obj-C's messaging?
I think Qt's S&S is more of a superset. Qt allows a signal to trigger
many slots, while Obj-C have only one target. In short, one button click
invokes a single action, in Obj-C, while in Qt it could invoke a series
of actions.
This is more of a design limitation in Cocoa, not in Objective-C.
On the plus-side of Cocoa is that a "signal"/"action" do not need to
have a target set, but can dynamically find it's target using a
responder chain, for example targetting the top-most windows document
controller from a single menu item.
Post by Bill Baxter
- Could Qt S&S be implemented using Obj-C messaging?
Yes, no problem. And no hacks :).
Post by Bill Baxter
- Could Obj-C-like messaging be implemented using Qt S&S?
Yes, with some problem. The responder chain mechanism needs to be
implemented.
Post by Bill Baxter
- Qt S&S includes an observer pattern in that emit() will call all
connected slots. Is this built into Obj-C messaging too?
As I mentioned Cocoa only use one action. So the equivalent of emit()
would be performAction. But it can only be hooked up to a single
target/slot.
Post by Bill Baxter
- Qt requires derivation from QObject to participate in S&S. Does
Obj-C also require deriving from a particular base object? Is it
explicit?
More or less. All existing senders are subclasses of NSControl, so using
those subclasses will let you use say [foo sendAction], and such shorter
things. In the same way subclasses of NSResponder will automatically fit
in the responder chain.
But in practice, Obj-C will not care as much of the classes, but of what
the classes implement. So if you send the action foo: to bar what the
}
And yes, if it does not respond, it is no error, unless you want it to
be, it is perfctly legal to call methods that are not implemented :).
Post by Bill Baxter
- What is the overhead to support Obj-C messaging in a class? Is
there a way to create an Obj-C class that doesn't support messaging?
The Obj-C language is build upon this message dispatch, so no way around
it, each "method call" is a message dispatch. And there is a overhead as
compared to C++. The run-time uses caching and other neat tricks, so in
practice a Obj-C method call cost about 2.5 C++ method calls.
Post by Bill Baxter
- Do people use Obj-C messaging for anything besides GUIs?
Oooh, yes. The real power here is in the dynamic dispatching of
messages. Best of all is what is called categories. You can extend a
class by subclassing, or by adding a category.
NSArray is a base class for static arrays.
NSMutableArray is a subclass of NSArray that is mutable (dynamic).
If you wanted to add a method say something useful as reversedArray to
them, then in C++ (And D) you would need to make two subclasses, one to
NSArray, and one to NSMutableArray, and it would be dead on impossible
make a function accept both without typecasting (Ok, add an interface
then). In Obj-C you can instead add a category to NSArray, and it will
@interface NSArray (ReversedCat)
- (NSArray *)reversedArray;
@end
myFoo.write("bar.txt", true);
vs
Same thing cn be done with lots of comments, but is rarely done. And
short names have already become a bad habit/convention anyway.
Post by Bill Baxter
The goal of this questioning, of course, is to encourage discussion
about whether these or any other form dynamic binding could / should
be added to D.
Could: YES! The first Obj-C compilers where simple preprocessors for C.
I see no real problem in linking with the GNU Obj-C runtime. And Obj-C
as such is very tiny, the power lies in the flexibility of the little
there is.
Should: Not too sure. I would like it, my only problem with Obj-C is the
C part, so replacing that with D would be nice. But I seriously doubt it
is worth the trouble, mostly because it is a quite different paradigm,
and before you understand it you cannot appreciate it.
Post by Bill Baxter
I've heard many people in C++ land say things to the effect of "Bah,
those silly Qt people weren't smart enough realize that you can
implement signals and slots directly in C++". But I've not been
particularly impressed by the pure C++ S&S libraries I've seen. On
the other hand, I found Qt's S&S to be simple, clean, straightforward,
and very easy to use. And I've not heard anything but praise about
making GUIs with Obj-C. Lutger's S&S for D posted earlier looks very
nice, but there must be something neat that Qt S&S--being dynamic--can
do that isn't possible with the static S&S solutions. Like
enumerating available signals for use in a GUI builder tool.
- Is it possible to mix D-style classes with Obj-C style messaging?
Apple's Objective-C++ apparently doesn't allow it.
http://developer.apple.com/releasenotes/Cocoa/Objective-C++.html
I.e. a class is either a C++ class or an Obj-C class. They can call
each other, but they are separate. You can't send an Obj-C message to
a C++ class. I think the ideal, though, would be something closer to
Qt where you have the ability to make any method you want be a slot.
In Qt those methods remain valid C++ methods, but you can also call
them by name, effectively.
This is because C++/D and Obj-C works very differently. Lets call the
object that will have a method called the reciever.
What C++/D does is very simply put: classes are structs with hidden
function pointers, when calling a method it looks up the function
pointer at a static offset from the reciever, and jumps. And the class
better make sure there is a valid function at the other end.
What Obj-C does is that it takes the reciever, and requested method
message and send to objc_msgSend(), that function looks up the correct
function pointer for the given reciever and method pair, if found it
jumps there. If not found it can raise en exception, pass control to a
"unhandled message" method, or silently ignore.
Oh well, hopefully you have less question now at least :).
// Fredrik Olsson
Lucas Goss
2006-09-27 12:45:44 UTC
Permalink
Post by Bill Baxter
Gotta go, but I think some sort of built-in dynamic dispatch mechanism
like this would have to be part of my "dream language".
--bb
I think I'm of the same opinion. I'm just starting to learn Obj-C now...

lucas
Fredrik Olsson
2006-09-27 14:26:34 UTC
Permalink
Post by Lucas Goss
Post by Bill Baxter
Gotta go, but I think some sort of built-in dynamic dispatch mechanism
like this would have to be part of my "dream language".
--bb
I think I'm of the same opinion. I'm just starting to learn Obj-C now...
lucas
I want to agree as well. But hmm... how D and Obj-C tackles OOP is so
very different that I can not see any way to merge the two.

So just as you can not seamlessly mix C++ classes and Obj-C classes in
Objective-C++, I can not see how D classes and Obj-C classes could be
mixes seamlessly in any practical way.

So if (a big IF) Obj-C type classes should ever be added to D I think an
Objective-D dialect, just as Objective-C++. As a bonus there would:
1. Not be reinventing the wheel.
2. Reuse the GNU Obj-C runtime (Already optimized).
3. Reuse/link against GNUStep

I think it would be just like C<->D where code is binary compatible, and
similar enough for anyone to learn. And it has already been done, with
Objective Modula-2, so there is a test case to learn from.

And as I have said before; my only problem with Obj-C is C. So the
thought of Objective-D appeals to me :). Garbage collection, foreach,
etc. Hmm... all of which are features mentioned by Apple to be part of
Objective-C 2.0 that comes next spring with OS X 10.5. But well,
backward compatible can be a heavy anchor.


// Fredrik Olsson
Lutger
2006-09-27 15:55:03 UTC
Permalink
Fredrik Olsson wrote:
<snip>
Post by Fredrik Olsson
Each object can have an action and a target. An action is an event that
is signaled at run-time, and the target is an object instance to call.
If target is nil (null) then the action will be sent to the responder
chain, instead of a predestined object.
The responder chain is implemented in the NSResponder protocol
(Interface) and will send the action down the controllers is logical
order acording to how windows are stacked, ending up in the
NSApplication instance if no one else is interested. This make sure that
if a single menu item (OSX == one menu you know :) ) has nil as target,
then the topmost window will get a chance to respond first, and yet the
same item will work for all windows.
[obj1 setTarget:obj2];
[obj1 sendAction:[obj1 action] to:[obj1 target]];
which will cause the valueChanged: method of obj2 to be performed. In
reality most classes have shortcuts such as sendAction, and even more so
you rarely need to care about sending manually at all.
Sounds good, but isn't it quite possible to implement this in D with a
more flexible messaging system than templated S&S?
Post by Fredrik Olsson
Post by Bill Baxter
- Qt requires derivation from QObject to participate in S&S. Does
Obj-C also require deriving from a particular base object? Is it
explicit?
More or less. All existing senders are subclasses of NSControl, so using
those subclasses will let you use say [foo sendAction], and such shorter
things. In the same way subclasses of NSResponder will automatically fit
in the responder chain.
But in practice, Obj-C will not care as much of the classes, but of what
the classes implement. So if you send the action foo: to bar what the
}
This is also a benefit of templates, no need for a superclass and free
functions, literal functions and delegates work too.
Post by Fredrik Olsson
And yes, if it does not respond, it is no error, unless you want it to
be, it is perfctly legal to call methods that are not implemented :).
Post by Bill Baxter
- What is the overhead to support Obj-C messaging in a class? Is
there a way to create an Obj-C class that doesn't support messaging?
The Obj-C language is build upon this message dispatch, so no way around
it, each "method call" is a message dispatch. And there is a overhead as
compared to C++. The run-time uses caching and other neat tricks, so in
practice a Obj-C method call cost about 2.5 C++ method calls.
According to QT, templated S&S is approximately 4x the cost of a
function call and QT's S&S is 10x the cost. So 2.5 certainly looks
acceptably to me, but this cost is paid for all calls right? And if I
understood this correctly, this also means Obj-C cannot inline member
functions?
Post by Fredrik Olsson
Post by Bill Baxter
- Do people use Obj-C messaging for anything besides GUIs?
Oooh, yes. The real power here is in the dynamic dispatching of
messages. Best of all is what is called categories. You can extend a
class by subclassing, or by adding a category.
NSArray is a base class for static arrays.
NSMutableArray is a subclass of NSArray that is mutable (dynamic).
If you wanted to add a method say something useful as reversedArray to
them, then in C++ (And D) you would need to make two subclasses, one to
NSArray, and one to NSMutableArray, and it would be dead on impossible
make a function accept both without typecasting (Ok, add an interface
then). In Obj-C you can instead add a category to NSArray, and it will
@interface NSArray (ReversedCat)
- (NSArray *)reversedArray;
@end
Thanks for this explanation,I'm going to look into this Objective C
thing as it seems interesting.
Post by Fredrik Olsson
<snip>
Post by Bill Baxter
I've heard many people in C++ land say things to the effect of "Bah,
those silly Qt people weren't smart enough realize that you can
implement signals and slots directly in C++". But I've not been
particularly impressed by the pure C++ S&S libraries I've seen. On
the other hand, I found Qt's S&S to be simple, clean, straightforward,
and very easy to use. And I've not heard anything but praise about
making GUIs with Obj-C. Lutger's S&S for D posted earlier looks very
nice, but there must be something neat that Qt S&S--being dynamic--can
do that isn't possible with the static S&S solutions. Like
enumerating available signals for use in a GUI builder tool.
Yes, you could say they fulfill different purposes. This article
compares them and even makes a point of using them side by side:
http://www.scottcollins.net/articles/a-deeper-look-at-signals-and-slots.html
Post by Fredrik Olsson
Post by Bill Baxter
- Is it possible to mix D-style classes with Obj-C style messaging?
Apple's Objective-C++ apparently doesn't allow it.
http://developer.apple.com/releasenotes/Cocoa/Objective-C++.html
I.e. a class is either a C++ class or an Obj-C class. They can call
each other, but they are separate. You can't send an Obj-C message to
a C++ class. I think the ideal, though, would be something closer to
Qt where you have the ability to make any method you want be a slot.
In Qt those methods remain valid C++ methods, but you can also call
them by name, effectively.
This is because C++/D and Obj-C works very differently. Lets call the
object that will have a method called the reciever.
What C++/D does is very simply put: classes are structs with hidden
function pointers, when calling a method it looks up the function
pointer at a static offset from the reciever, and jumps. And the class
better make sure there is a valid function at the other end.
What Obj-C does is that it takes the reciever, and requested method
message and send to objc_msgSend(), that function looks up the correct
function pointer for the given reciever and method pair, if found it
jumps there. If not found it can raise en exception, pass control to a
"unhandled message" method, or silently ignore.
Putting aside performance, it looks to me that the main difference is
that Objective-C has good support for reflection. Maybe I'm wrong, but
I'd think better reflection (wherever it comes from) support would
enable to write the things you'd want to do in 'Objective-D' in D. Or
not? Excuse my ignorance of Obj-C.
Josh Stern
2006-09-27 17:05:26 UTC
Permalink
On Wed, 27 Sep 2006 17:55:03 +0200, Lutger wrote:

I found this comparison of different C++ approaches to signal slots
with a web search.

http://slotsig.sourceforge.net/doc/features-compare.html

Can't vouch for the validity of the summary, but it might be a good
starting point for further investigation.
Lutger
2006-09-27 18:44:05 UTC
Permalink
Post by Josh Stern
I found this comparison of different C++ approaches to signal slots
with a web search.
http://slotsig.sourceforge.net/doc/features-compare.html
Can't vouch for the validity of the summary, but it might be a good
starting point for further investigation.
Nice list, there are also a few benchmarks there. Depending on
interpretation of course, my sigslots library scores equal points
feature-wise as slotsig. There are some features in slotsig which might
be worth investing, thank you for the link.
These lists are always biased, but the biggest advantages of QT are
not listed: dynamic connections which make it possible to, for example,
script connections, load from xml resource, etc. This is where string
based sigslots or - as I understand - Objective C is superior to the
template-based implementations.
Josh Stern
2006-09-27 19:50:33 UTC
Permalink
Post by Lutger
Post by Josh Stern
I found this comparison of different C++ approaches to signal slots
with a web search.
http://slotsig.sourceforge.net/doc/features-compare.html
Can't vouch for the validity of the summary, but it might be a good
starting point for further investigation.
Nice list, there are also a few benchmarks there. Depending on
interpretation of course, my sigslots library scores equal points
feature-wise as slotsig. There are some features in slotsig which might
be worth investing, thank you for the link.
These lists are always biased, but the biggest advantages of QT are
not listed: dynamic connections which make it possible to, for example,
script connections, load from xml resource, etc. This is where string
based sigslots or - as I understand - Objective C is superior to the
template-based implementations.
The issues of what has to be decided at design time, compile time, and
run time in order to use signals and slots are important.
Requiring inheritance from QObject for some things is one kind
of strong restriction, and requiring connections specified at
compile time is another. There are language vs. library issues
involved here. A (the?) key language feature seems to be the question of
what kind of support does the language provide for making it easy to
attach a "hook" to a given function (where hook means roughly "now
Mr.Ffunction, from now on, before you exit, please call this other
function I'm about to tell you about with your return value as
its input and maybe some other info like a pointer to your object in case
you are a member function"). I agree with the implicit point made by the
slotsig guy that part of this mechanism ideally should give the user
options about thread-safety and thread-locality. Seems like if the
language provides a really good hook mechanism, a lot of convenient
library stuff can be built on top to taste. Intuitively it seems like D's
system of Boxs and delegates could be put to good use towards finding
attractive possibilities within the library problem design space, and
having GC to eliminate most ownership issues makes many solutions a lot
simpler.
Lutger
2006-09-27 21:53:29 UTC
Permalink
Josh Stern wrote:
<snip>
Post by Josh Stern
The issues of what has to be decided at design time, compile time, and
run time in order to use signals and slots are important.
Requiring inheritance from QObject for some things is one kind
of strong restriction, and requiring connections specified at
compile time is another. There are language vs. library issues
involved here. A (the?) key language feature seems to be the question of
what kind of support does the language provide for making it easy to
attach a "hook" to a given function (where hook means roughly "now
Mr.Ffunction, from now on, before you exit, please call this other
function I'm about to tell you about with your return value as
its input and maybe some other info like a pointer to your object in case
you are a member function"). I agree with the implicit point made by the
slotsig guy that part of this mechanism ideally should give the user
options about thread-safety and thread-locality. Seems like if the
language provides a really good hook mechanism, a lot of convenient
library stuff can be built on top to taste. Intuitively it seems like D's
system of Boxs and delegates could be put to good use towards finding
attractive possibilities within the library problem design space, and
having GC to eliminate most ownership issues makes many solutions a lot
simpler.
Yes, although I would not see requiring connections at compile time as a
restriction, I would file this under 'feature' as it enables
compile-time type checking. It's a choice really, connections at runtime
are more flexible but less safe and incur performance cost. Requiring
inheritance (but more so custom preprocessor) in QT is needed to make up
for lack of introspection in C++.
Ideally you'd have both systems available to choose the appropiate one
for what you want.
Bill Baxter
2006-09-27 18:17:25 UTC
Permalink
Howdy.
Post by Fredrik Olsson
Each object can have an action and a target.
By this you mean each GUI widget can have an action and target, right?
Post by Fredrik Olsson
An action is an event that
is signaled at run-time, and the target is an object instance to call.
If target is nil (null) then the action will be sent to the responder
chain, instead of a predestined object.
The responder chain is implemented in the NSResponder protocol
(Interface) and will send the action down the controllers is logical
order acording to how windows are stacked, ending up in the
NSApplication instance if no one else is interested.
So it forms a kind of tree or funnel with leaves being widgets, and the
root being the NSApplication instance.
Post by Fredrik Olsson
This make sure that
if a single menu item (OSX == one menu you know :) ) has nil as target,
then the topmost window will get a chance to respond first, and yet the
same item will work for all windows.
Don't really follow you there. Why does the topmost window get the
first chance? Just before you said it went up a chain, so it seems like
the immediate container window of the item would get the first chance,
and eventually the topmost window will get a chance.

Anyway, this part of your description seems much more Cocoa than
Objective C. I.e. it seems independent of the language itself, more or
less just the classic "chain of responsibility" pattern. Just something
implemented on top of the messaging sys provided by Obj-C.
Post by Fredrik Olsson
[obj1 setTarget:obj2];
[obj1 sendAction:[obj1 action] to:[obj1 target]];
which will cause the valueChanged: method of obj2 to be performed. In
reality most classes have shortcuts such as sendAction, and even more so
you rarely need to care about sending manually at all.
Ok, I'm trying to grok these message things now.
It looks like there's no distinction between method names and call
setAction looks sort of like a method with parameter being a selector.
Post by Fredrik Olsson
[obj1 sendAction:[obj1 action] to:[obj1 target]];
it looks like there are two methods, 'sendAction' and 'to'.
And I take it [obj1 action] is a named attribute lookup, similar to a
QProperty?
Post by Fredrik Olsson
Post by Lucas Goss
Post by Bill Baxter
Gotta go, but I think some sort of built-in dynamic dispatch
mechanism like this would have to be part of my "dream language".
I think I'm of the same opinion. I'm just starting to learn Obj-C now...
I want to agree as well. But hmm... how D and Obj-C tackles OOP is so
very different that I can not see any way to merge the two.
Is it really so difficult? Maybe I just don't understand how Obj-C
works well enough, but in Obj-C you have both regular C function calls
(do_something(foo)) and message passing ([obj doSomething:foo]) and the
user decides which paradigm to use at what time. Similarly in an Obj-D
you could have regular method calls (obj.do_something(foo)) and
messaging calls ([obj doSomething:foo]).

It seems like it could work more or less the way slots do in Qt. If I have:
# slot:
# void callMeLater(int val);

In a Qt program, then callMeLater is a valid method that can be called
like any other method. But it is *also* callable via dynamic lookup
using QObject's under-the-hood moc-generated mechanisms. I don't see why
a similar idea wouldn't work for adding a touch of Obj-C to D.
Post by Fredrik Olsson
So just as you can not seamlessly mix C++ classes and Obj-C classes in
Objective-C++, I can not see how D classes and Obj-C classes could be
mixes seamlessly in any practical way.
Maybe I'm just not seeing the full scope of how Obj-C works yet. But
nothing I've heard so far seems like an insurmountable hurdle.

It just doesn't seem a very attractive proposition to me to have to
decide at initial design time whether my class will have regular methods
or use dynamic messaging. I may know I want to start out with one or
the other, but then I want my static class to recieve a particular
message from a GUI. I guess these guys at Apple have given it some
thought with Obj-C++, but my initial reaction was that keeping the types
of classes completely separate must be some kind of corner cutting to
get the thing out the door quickly, or perhaps having something to do
with preserving C++ compatibility.

--Bill
Fredrik Olsson
2006-09-28 07:46:08 UTC
Permalink
Post by Bill Baxter
Howdy.
Post by Fredrik Olsson
Each object can have an action and a target.
By this you mean each GUI widget can have an action and target, right?
Yes. Or in practice three combination (A = action set, T = target set):
A && T = Will trigger A in T.
A && !T = Will trigger A in responder chain.
!A = Will rigger nothing, ignores T.
Post by Bill Baxter
Post by Fredrik Olsson
An action is an event that is signaled at run-time, and the target is
an object instance to call. If target is nil (null) then the action
will be sent to the responder chain, instead of a predestined object.
The responder chain is implemented in the NSResponder protocol
(Interface) and will send the action down the controllers is logical
order acording to how windows are stacked, ending up in the
NSApplication instance if no one else is interested.
So it forms a kind of tree or funnel with leaves being widgets, and the
root being the NSApplication instance.
Yes.
Post by Bill Baxter
Post by Fredrik Olsson
This make sure that if a single menu item (OSX == one menu you know :)
) has nil as target, then the topmost window will get a chance to
respond first, and yet the same item will work for all windows.
Don't really follow you there. Why does the topmost window get the
first chance? Just before you said it went up a chain, so it seems like
the immediate container window of the item would get the first chance,
and eventually the topmost window will get a chance.
Anyway, this part of your description seems much more Cocoa than
Objective C. I.e. it seems independent of the language itself, more or
less just the classic "chain of responsibility" pattern. Just something
implemented on top of the messaging sys provided by Obj-C.
Yes the responder chain is implemented in Cocoa, but it relies heavily
on Obj-C's ability to let objects forward invocations of methods they do
not implement themselves.

The topmost window needs the first chance as if for example the user
presses Command-B for "make bold", then the first object that needs to
know about it is probably on the topmost object, and with the cursor in
it. The responder chain sends messages like this:
1. The key window?s first responder and successors, including objects
added with setNextResponder:
2. The key window itself
3. The key window?s delegate (which need not inherit from NSResponder)
4. The main window?s first responder and successors, including objects
added with setNextResponder:
5. The main window itself
6. The main window?s delegate (which need not inherit from NSResponder)
7. The application object, NSApp
8. The application object?s delegate (which need not inherit from
NSResponder)
Post by Bill Baxter
Post by Fredrik Olsson
[obj1 setTarget:obj2];
[obj1 sendAction:[obj1 action] to:[obj1 target]];
which will cause the valueChanged: method of obj2 to be performed. In
reality most classes have shortcuts such as sendAction, and even more
so you rarely need to care about sending manually at all.
Ok, I'm trying to grok these message things now.
It looks like there's no distinction between method names and call
setAction looks sort of like a method with parameter being a selector.
Post by Fredrik Olsson
[obj1 sendAction:[obj1 action] to:[obj1 target]];
it looks like there are two methods, 'sendAction' and 'to'.
And I take it [obj1 action] is a named attribute lookup, similar to a
QProperty?
Hmm... now this is strange, and it took a while for me to grasp it as
well :). Lets take this one:
[obj1 sendAction:[obj1 action] to:[obj1 target]]
It is actually three method calls, two of them nested.
[obj1 action] is calling obj1's method action, and that method returns a
selector, a selector is a method.
[obj1 target] is also a method call, but returning an object instance.

So you could rewrite that as:
SEL selector = [obj1 action];
id target = [obj1 target];
[obj1 sendAction:action to:target];
This last statement is a single method call, with two arguments, and no
result obviously. The name of the method is "sendAction:to:", so if you
wanted the selector for that method you would do:
SEL selector = @selector(sendAction:to:);

Methods with : in their names takes parameters, one parameter after each
:, and sometimes a list of parameters after the last :.
You would for example use the "fileExistsAtPath:isDirectory:" method of
a NSFileManager object to check if a file exists, and if it then is a
directory. Used like this:
id fm = [NSFileManager defaultManager]; // Get the shared instance
BOOL isDir = NO;
BOOL doesExist = [fm fileExistsAtPath:@"/tmp/foo" isDirectory:&isDir];

If this syntax look wierd, then here is the method definition :) :
- (BOOL)fileExistsAtPath:(NSString *)path
isDirectory:(BOOL *)isDirectory
{
...
}
Post by Bill Baxter
Post by Fredrik Olsson
Post by Lucas Goss
Post by Bill Baxter
Gotta go, but I think some sort of built-in dynamic dispatch
mechanism like this would have to be part of my "dream language".
I think I'm of the same opinion. I'm just starting to learn Obj-C
now...
Post by Fredrik Olsson
I want to agree as well. But hmm... how D and Obj-C tackles OOP is so
very different that I can not see any way to merge the two.
Is it really so difficult? Maybe I just don't understand how Obj-C
works well enough, but in Obj-C you have both regular C function calls
(do_something(foo)) and message passing ([obj doSomething:foo]) and the
user decides which paradigm to use at what time. Similarly in an Obj-D
you could have regular method calls (obj.do_something(foo)) and
messaging calls ([obj doSomething:foo]).
Well... D-methods, and Obj-C methods are invoked in very different ways.
Their "bhind the scenes" implementation is vastly different. And I see
no easy way to treat a D-method as if it where a Obj-C-method, and vice
versa.
Post by Bill Baxter
# void callMeLater(int val);
In a Qt program, then callMeLater is a valid method that can be called
like any other method. But it is *also* callable via dynamic lookup
using QObject's under-the-hood moc-generated mechanisms. I don't see why
a similar idea wouldn't work for adding a touch of Obj-C to D.
Everything can be done, I just think that if you want interoperability,
and syntax compatibility with existing D-methods then you will have to
make trade offs. And with those tradeoffs, you lose much of the power
from Obj-C. And then a template based S&S solution would be best.

In the end a template based S&S is probably the way to go anyway, D was
never intended to use the Smalltalk school of OOP.
Post by Bill Baxter
Post by Fredrik Olsson
So just as you can not seamlessly mix C++ classes and Obj-C classes in
Objective-C++, I can not see how D classes and Obj-C classes could be
mixes seamlessly in any practical way.
Maybe I'm just not seeing the full scope of how Obj-C works yet. But
nothing I've heard so far seems like an insurmountable hurdle.
It just doesn't seem a very attractive proposition to me to have to
decide at initial design time whether my class will have regular methods
or use dynamic messaging. I may know I want to start out with one or
the other, but then I want my static class to recieve a particular
message from a GUI. I guess these guys at Apple have given it some
thought with Obj-C++, but my initial reaction was that keeping the types
of classes completely separate must be some kind of corner cutting to
get the thing out the door quickly, or perhaps having something to do
with preserving C++ compatibility.
Objective-C++ does not touch any of the ++ parts of C. Just as
Objective-C does not touch anything of how C works. Objective-C is a
pure superset on top. So Objective-C++ is in reality a programming
language with two OOP implementations. One from the Simula school; the
untouched C++, and one from the Smalltalk school; the very same superset
as used in Objective-C.

The ++-classes have no clue that the Objective-classes exists, and vice
versa.

"Objective" do only add one syntactic element to C (Or C++); message
passing, to invoke methods. And for this it uses the [object message]
syntax. For the rest of "Objective" the preprocessor roots can very
easily be seen; for one all keywords begin with the @ character.
@selector(foo)
@interface MyClass : SuperClass
@end
etc.
And all they do is constructing constants, and "hidden" functions calls
to setup the run-time at program start. Something that could easily be
stuffed away in static constructors of each module in D.


// Fredrik Olsson
d
2006-09-28 12:05:09 UTC
Permalink
Post by Fredrik Olsson
Hmm... now this is strange, and it took a while for me to grasp it as
[obj1 sendAction:[obj1 action] to:[obj1 target]]
It is actually three method calls, two of them nested.
[obj1 action] is calling obj1's method action, and that method returns a
selector, a selector is a method.
[obj1 target] is also a method call, but returning an object instance.
The best explanation is that Objective-C is modelled after Smalltalk. A
method in C might be:

int AddAToX(int& a, int x);

where as in Objective C it would be:

- (int) Add: (int) a To: (int) x;

where the Method signature is Add:To:. Smalltalk would use almost the same
structure.
Bill Baxter
2006-10-01 04:44:13 UTC
Permalink
Hey there,
Post by Fredrik Olsson
Post by Bill Baxter
Post by Fredrik Olsson
[obj1 sendAction:[obj1 action] to:[obj1 target]];
it looks like there are two methods, 'sendAction' and 'to'.
And I take it [obj1 action] is a named attribute lookup, similar to a
QProperty?
Hmm... now this is strange, and it took a while for me to grasp it as
[obj1 sendAction:[obj1 action] to:[obj1 target]]
It is actually three method calls, two of them nested.
[obj1 action] is calling obj1's method action, and that method returns a
selector, a selector is a method.
[obj1 target] is also a method call, but returning an object instance.
That's very interesting. Can you also reverse the order of arguments in
the call, like to:sendAction:? Or is that a different method?
[obj1 to:[obj1 target] sendAction:[obj1 action]]

--bb
Fredrik Olsson
2006-10-02 07:16:32 UTC
Permalink
Post by Bill Baxter
Hey there,
Post by Fredrik Olsson
Post by Bill Baxter
Post by Fredrik Olsson
[obj1 sendAction:[obj1 action] to:[obj1 target]];
it looks like there are two methods, 'sendAction' and 'to'.
And I take it [obj1 action] is a named attribute lookup, similar to a
QProperty?
Hmm... now this is strange, and it took a while for me to grasp it as
[obj1 sendAction:[obj1 action] to:[obj1 target]]
It is actually three method calls, two of them nested.
[obj1 action] is calling obj1's method action, and that method returns
a selector, a selector is a method.
[obj1 target] is also a method call, but returning an object instance.
That's very interesting. Can you also reverse the order of arguments in
the call, like to:sendAction:? Or is that a different method?
[obj1 to:[obj1 target] sendAction:[obj1 action]]
--bb
That would be a different method. The full method declaration is:
- (void)sendAction:(SEL)action to:(id)target;
But the method signature is always typeless and is thus:
sendAction:to:
In practice the type SEL is a char*, and @selector(sendAction:to:) will
be a char* to the null terminated string "sendAction:to:". What the
@selector() "macro" does is to guarantee that there is only a single
pointer to each method signature string so that
if ([item action] == @selector(removeUser:)) { ... }
is guaranteed to work.

Would be nice if you could rearrange the arguments though. But well,
they are part of the method signature, not named arguments.


// Fredrik Olsson

Fredrik Olsson
2006-09-26 08:01:45 UTC
Permalink
Bill Baxter skrev:
<snip>
Post by Bill Baxter
- Could Qt S&S be implemented using Obj-C messaging?
Easier then I thought actually. I did it just for fun, as a category on
the root class NSObject so all classes get the functionality. And it
turned out to require 174 SLOC (Source Lines Of Code), and then much is
convenience code that is not really needed. A minimal implementation
would easily go under 100 lines of code.

The message passing is already build in, so all I did was using some
existing classes to emulate the Qt behavior. One for sets to store a set
of target objects. And then a hash map to store a dictionary (with the
instance as key) of such sets for each instance with connected signals.

Oh well, I attach the code, and an example using it. Compiles with Xcode
2.2. Should work with with OSX 10.0 and up, and GNUStep as well.
Post by Bill Baxter
- Could Obj-C-like messaging be implemented using Qt S&S?
Stretching the truth one could say the the Qt S&S emitting are Obj-C
like messaging, but with less optimization, only implemented for one
special case, whereas Obj-C is made for the more general case. I see it
as Obj-C messages with a C++ syntax.
Post by Bill Baxter
- Qt S&S includes an observer pattern in that emit() will call all
connected slots. Is this built into Obj-C messaging too?
No, but as can be seen in the code I attach it can very easily be
emulated. Just keep the targets in a collection instance such as NSSet,
NSArray or NSDictionary, and you can use makeObjectsPerformSelector: to
"call all".


// Fredrik Olsson
-------------- next part --------------
A non-text attachment was scrubbed...
Name: Signals.zip
Type: application/zip
Size: 7609 bytes
Desc: not available
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20060926/8b512b9f/attachment.zip>
Loading...