home *** CD-ROM | disk | FTP | other *** search
- Xref: sparky comp.lang.c++:13501 comp.windows.open-look:3794 alt.toolkits.xview:855
- Path: sparky!uunet!sun-barr!news2me.ebay.sun.com!jethro.Corp.Sun.COM!exodus.Eng.Sun.COM!appserv.Eng.Sun.COM!midniteoil!soloway
- From: soloway@midniteoil.Eng.Sun.COM (Mark Soloway)
- Newsgroups: comp.lang.c++,comp.windows.open-look,alt.toolkits.xview
- Subject: C++ and callback problems (VERY LONG)
- Date: 10 Sep 1992 22:28:52 GMT
- Organization: Sun Microsystems, Inc.
- Lines: 156
- Distribution: world
- Message-ID: <lavj14INN4ul@appserv.Eng.Sun.COM>
- Reply-To: soloway@midniteoil.Eng.Sun.COM
- NNTP-Posting-Host: midniteoil
-
- From <name kept anonymous to protect the innocent>:
-
- > This letter concerns the your article in alt.toolkits.xview. I have
- > tried to implement your method of encapsulating callbacks thru a
- > static wrapper function and storing the 'this' pointer as xv_data.
- > Two problems have arisen: the first was due to the fact that i ignored
- > your short and somewhat cryptic note:
- > -> // If a notify handler has been specified, via
- > -> // "void Button::setNotifyHandler (void (*)(Button *, Event *))",
- > -> // then call it.
- > -> if (object->notifyHandler)
- > -> (*object->notifyHandler)(object, event);
- >
- > I called directly object->notifyhandler(), but then calls in derived classes
- > were made to the ancestor callback, as the value of
- > object->notifyhandler() is known at compile-time. I then realized what
- > u did, and added a private variable which points to the callback, thus
- > sort of explicitly writing the late-binding code. What turns out
- > (using g++ 2.1), is that the code is unusable, because the
- > private handler receives a hidden this pointer as its first parameter,
- > but no such parameter is pushed to the stack in:
- > -> (*object->notifyHandler)(event);
- > thus, stepping into a call of the form
- > (*object->notifyhandler(menu, menuitem)
- > where menu=x and menuitem=y, and notifyhandler pointing at notifyhandlerproc
- > yields
- > notifyhandlerproc(this=x, menu=y, menuitem=junk)
- >
- > i could explicitly define the variable notifyhandlerproc to be a
- > pointer to a function which receives (obj *, Menu, Menu_item), but how
- > portable is this? and since you stated in your article that this
- > method was used in uit, can you please let me know what the portable,
- > arm-compliant, overall stable workaround is?
-
- After re-reading what I wrote, I can see why my original article may have
- been confusing. I left out a class declaration that would have made example
- #1 more clear and I made a mistake in the "notifyProc" part of example
- #2 that could make the example very confusing. In order to correct these
- mistakes, I've included portions of the original posting along with commentary
- that will hopefully clear up the confusion.
-
- -> This article describes a method I use to provide a convenient C++
- -> callback interface for XView and provide the ability to encapsulate
- -> callback behavior in a subclass. The method described is used in
- -> UIT V2.
-
- [text deleted]
-
- EXAMPLE 1:
-
- -> A basic notifyProc member function that calls a user spcified callback
- -> handler might look like this:
- ->
- -> void Button::notifyProc (Panel_item item, Event *event)
- -> {
- -> Button *object = (Button *)xv_get(item,
- -> XV_KEY_DATA,
- -> THIS_POINTER_KEY);
- ->
- -> // If a notify handler has been specified, via
- -> // "void Button::setNotifyHandler (void (*)(Button *, Event *))",
- -> // then call it.
- -> if (object->notifyHandler)
- -> (*object->notifyHandler)(object, event);
- -> }
-
- The "notifyHandler" member used here is actually a data member. The class
- might look something like this:
-
- class Button {
- public:
- ...
- void setNotifyHandler (void (*handler)(Button *, Event *))
- {
- notifyHandler = handler;
- }
-
- protected:
- Panel_item xviewButton;
-
- private:
- static void notifyProc(Panel_item, Event *);
- void (*notifyHandler)(Button *, Event *);
- }
-
- The notifyHandler data member is just a holder for a user specified
- callback function. The user specified callback function should be
- a regular external function (not a member function of another or this
- class).
-
- The function that XView actually calls for the PANEL_NOTIFY_PROC is
- "notifyProc". "notifyProc" does not have an implicit "this" parameter
- because it is a static member function. "notifyProc" needs to be
- declared public for use with g++ because it is illegal to use the
- address of a private or protected member function (static or non-static)
- in g++. This is not the case for AT&T or ANSI C++.
-
- -> This provides a "convenient" callback interface, but it does not provide
- -> for encapsulation of callback behavior in the class. To provide the ability
- -> to encapsulate the behavior, you need to provde a virtual function that
- -> will be overridden in subclasses that are encapsulating the callback
- -> behavior:
-
- EXAMPLE 2:
-
- -> class Button {
- -> public:
- -> ...
- ->
- -> protected:
- -> // Make xviewButton protected so that derived classes can get hold
- -> // of the XView button object when inside of their personalized
- -> // handlers.
- -> Panel_item xviewButton;
- ->
- -> private:
- -> static void notifyProc(Panel_item, Event *);
- -> virtual void notifyHandler(Event *);
- -> }
- ->
- -> void Button::notifyProc (Panel_item item, Event *event)
- -> {
- -> Button *object = (Button *)xv_get(item,
- -> XV_KEY_DATA,
- -> THIS_POINTER_KEY);
- ->
- -> (*object->notifyHandler)(event);
- -> }
-
- The "notifyHandler" in this example is an actual member function of the
- class. It should be called as such. Since I made a mistake in this
- example, this is where most of the confusion probably is. The above
- "notifyProc" should be re-written as follows:
-
- void Button::notifyProc (Panel_item item, Event *event)
- {
- Button *object = (Button *)xv_get(item,
- XV_KEY_DATA,
- THIS_POINTER_KEY);
-
- object->notifyHandler(event);
- }
-
- -> You can then define the behavior of notifyHandler in a class derived
- -> from Button:
-
- [text deleted]
-
- - Mark
- __________________________________________
- \_Mark Soloway (mark.soloway@Eng.Sun.COM)_\
- /_Distributed Systems Services (ToolTalk)_/
- \__SunSoft (A Sun Microsystems Company)___\
-
-
-
-