 |
 |
Bad IMP!
|
 |
|
 |
|
Mac Enthusiast
Join Date: Feb 2000
Location: Storrs,Connecticut, USA
Status:
Offline
|
|
Okay, Ali mentioned IMPs a while ago in another thread. I looked them up in the documentation and I have been able to successfully able to use them but there is one thing that is really bothering me. Below is a section right out of "Object Oriented Programming and the Objective C Language":
The example below shows how the procedure that implements thesetFilled:
method might be called:
void (*setter)(id, SEL, BOOL);
int i;
setter = (void (*)(id, SEL, BOOL))[target
methodForSelector:@selector(setFilled  ];
for ( i = 0; i < 1000, i++ )
setter(targetList[i], @selector(setFilled  , YES);
Okay, now I understand how to use this. What I want to know is the answer of WHY to a part. So, even if the method setFilled takes zero parameters, if I were to call setter, I'd still have to pass it the pointer to an object and the selector. Well, I thought that an IMP was kind of like a pointer to a specific method in a specific class. I mean, since when setter is initialized they even use the specific class that will be used, target, and the selector, setFilled, then why is it necessary to pass them to setter when it's called? I've make an IMP and when I invoked it I passed it the object associated, then I passed it nil instal of a selector. It worked perfectly. Then I tried passing it a selector that was totally different from the one that it was initialized with. It worked perfectly again. The only time that I ran into problems was when I tried to pass it a different object than that which it was supposed to take. Then my program quit because of a bus error when it got to that point. So what's so magical about those parameters? Why do they even have to be there?
|
|
|
| |
|
|
|
 |
|
 |
|
Forum Regular
Join Date: Sep 2000
Status:
Offline
|
|
When you call an Objective-C method, there are two hidden arguments that are passed in and available to the called function: One is the object, and the other is the selector. So although the method is:
- (void)setValue  int)i {
...
}
the function really has 3 arguments: id, SEL, and int.
Given IMP is just a function pointer, when you are using IMP, you need to supply these arguments.
Most of the time, methods rely on the object (self) to be correct, so if you don't pass in the object, things won't work right.
Most methods do not look at the selector at all (_cmd), so even if you pass in garbage for that, things will usually "work" fine.
Ali
|
|
|
| |
|
|
|
 |
|
 |
|
Mac Enthusiast
Join Date: Feb 2000
Location: Storrs,Connecticut, USA
Status:
Offline
|
|
Okay, I can think of lots of times where a method might need to know which object it belongs to, but when would it need to know which method is? ie. the selector argument. The only thing that I could guess is that the debugger might use it to help tell where you are.
|
|
|
| |
|
|
|
 |
|
 |
|
Fresh-Faced Recruit
Join Date: Jan 2001
Status:
Offline
|
|
The selector is what allows dynamic binding. Here goes! When you send [MyObject message:int]. You are really sending something like this: MyObject.send_msg(id,Sel,int). The reason is that all objects have the function send_msg so all the compiler sees is a whole bunch of send_msg functions and it can then do its normal compile time binding.
At run time when the object gets sent a message, what's really happening is that the send_msg function of the object gets called. It then looks up SEL in its table of selectors that it supports, calls the function that matches the selector and returns the result. This is the reason that "Object doesn't support message" is only a warning and the compiler compiles fine. If the send_msg function is given a SEL it doesn't have a function for, your program quits!
In recap: The actual final connection between the message you send and the function that get's called happens in the send_msg function as the message is getting sent. You can't get binding much later than that!! The people who invented object C were definently clever!
Note: The reason a selector is used instead of the whole function name being sent is purely a speed issue the whole name would have worked as well.
Note2: I may have made a few simple errors like the name of the send_msg function as i'm writing this from memory but i'm pretty sure I got the basic structure of the process right. If not someone correct me!
peter
|
|
|
| |
|
|
|
 |
|
 |
|
Fresh-Faced Recruit
Join Date: Jan 2001
Status:
Offline
|
|
I forgot, the reason the calling object is sent is so that the function get get more information from it if it needs it.
peter
Hope this all makes sense!
|
|
|
| |
|
|
|
 |
|
 |
|
Fresh-Faced Recruit
Join Date: Jan 2001
Status:
Offline
|
|
guys I just checked the objC pdf in the documentation (See page 80 of the file /Developer/Documentation/Cocoa/ObjectiveC/ObjC.pdf.). And i did get the name of the send_msg function wrong. It's called objc_msgsend.
Other than that I got the process right (not bad form memory).
"Most methods do not look at the selector at all (_cmd), so even if you pass in garbage for that, things will usually "work" fine."
If what the documentation says is true, I would of thought that the selector was more important than the id. Isn't the selector used when you use IMP? Does this bypass the objc_msgsend function and called the function directly?
sorry for the triple post.
peter
|
|
|
| |
|
|
|
 |
|
 |
|
Mac Enthusiast
Join Date: Feb 2000
Location: Storrs,Connecticut, USA
Status:
Offline
|
|
Yea, it bypasses the objc_msgsend function. An IMP is a pointer to a method, kind of like you can make a pointer to a function. When I set the IMP equal to something I am actually setting it equal to the address of a method. This way it doesn't need the selector, it's kind of accessing things directly. I can see why the object can be a necessary thing to pass: it uses that in order to identify self and super. The only thing that I don't get is why I'd ever need to pass the selector. I've been thinking that maybe passing the selector helps the debugger know where you are in the code. I haven't tried debugging my code with IMPs. I'll have to do that and see if it gets lost once it gets to the IMP. If that's the only reason for passing the selector then it isn't really necessary but I'd really think that there is another reason. (Why waste time passing variables just to help debugging? It's a waste in the finished product.) If anyone knows of a use where passing the selector when you use an IMP is necessary I'd be interested in finding out.
|
|
|
| |
|
|
|
 |
|
 |
|
Dedicated MacNNer
Join Date: Jan 2001
Location: Virginia, US
Status:
Offline
|
|
Right -- the IMP is the pointer to the function that implements the method.
The first argument must be the object -- this is the "self" variable in the implementation. The second is the selector used -- this is the "_cmd" variable in the implementation.
While virtually no methods actually use the _cmd variable, it is still part of the Objective-C definition, so it should always be passed just in case. It does occasionally get used, often as part of logging macros, as the name of the current method can be derived from _cmd without requiring it to be an extra argument to the macro.
A selector can be inlined as a compiler constant with @selector, e.g. @selector(paste  , so there's no performance penalty in passing it.
The gdb debugger doesn't use the second argument in any special way -- it knows the addresses of the functions from the symbol table. However, it is sometimes used in ad-hoc situations when pulling arguments off the stack frame to tell the difference between a regular C function and a method -- if the second argument is a selector, then in all likelyhood this is a method. Some gdb command-line tricks used over the years make use of voodoo like that. If you're really into it you can write some runtime code that walks up the stack and generates a back trace when exceptions occur, etc. I would guess this is what Apple's ExceptionHandling framework does.
[This message has been edited by lindberg (edited 01-27-2001).]
|
|
|
| |
|
|
|
 |
 |
|
 |
|
|
|
|
|

|
|
 |
Forum Rules
|
 |
 |
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
|
HTML code is Off
|
|
|
|
|
|
 |
 |
 |
 |
|
 |
|