fidelio@guug.UUCP (Michelle Nelson) (12/19/89)
Hello. I am having a problem setting up callback functions from a resource file. I would like to be able to choose which function is called from a particular menu item at run time and not compile it into the program. The error which I get when trying to use the following resource file definition Fbmenu*menu_item1*select: (* purchasing)() or this resource file definition Fbmenu*menu_item1*select: purchasing is: X Toolkit Warning: No type converter registered for 'String' to 'Callback' conversion. I know that the select resource wants a pointer to a function and that this is a string. There doesn't seem to be a converter from string to pointer... I am using the hp widgets and toolkit. Please let me know if you have any suggestions. (i.e. if I am being unreasonable about defining callbacks at runtime...) I am a relative newcomer to X windows programming. (e-mail would be greately appreciated as I am worried I would miss the response on the newsgroup.) Michelle Nelson
swick@ATHENA.MIT.EDU (Ralph R. Swick) (12/19/89)
I am having a problem setting up callback functions from a resource file. ... X Toolkit Warning: No type converter registered for 'String' to 'Callback' conversion. Not too surprising. While not impossible to accomplish, writing a procedure which would permit you to specify real function names in a resource file requires a considerable amount of operating-system- specific support. It has not been implemented (nor is it documented to be implemented or likely to be implemented in the near future :-) in any MIT release. To allow portable specification of procedure bindings in resource files, Xt provides another facility very similar to callbacks known as Action procedures. See chapter 10 of the Xt document. While not a replacement for callbacks, action procedures are most definitely intended to be used to do what you want: I would like to be able to choose which function is called from a particular menu item at run time and not compile it into the program. -Ralph R. Swick
brianw@gazooch.Sun.COM (Brian Warkentine) (12/20/89)
In article <8912191502.AA22891@LYRE.MIT.EDU> swick@ATHENA.MIT.EDU (Ralph R. Swick) writes: > > I am having a problem setting up callback functions from a resource file. > ... > X Toolkit Warning: No type converter registered for 'String' to 'Callback' > conversion. > > >Not too surprising. While not impossible to accomplish, writing a >procedure which would permit you to specify real function names >in a resource file requires a considerable amount of operating-system- >specific support. > [ ... ] >To allow portable specification of procedure bindings in resource >files, Xt provides another facility very similar to callbacks known >as Action procedures. >-Ralph R. Swick You're contradicting yourself. Since one can already bind action proc names to "real functions", why would it be operating system dependent to bind callback names to "real functions?" Suppose that callbacks could be registered in a fashion similar to action proc registration. The difference is subtle but its a win: A user could specify a callback in .Xdefaults (or where ever) without having to worry about what sequence of events are required to trigger that callback. -brian warkentine brianw@sun.com
grunwald@foobar.colorado.edu (Dirk Grunwald) (12/20/89)
>>>>> On 19 Dec 89 18:45:23 GMT, brianw@gazooch.Sun.COM (Brian Warkentine) said:
Brian> You're contradicting yourself. Since one can already bind action proc
Brian> names to "real functions", why would it be operating system dependent
Brian> to bind callback names to "real functions?"
---
Action procs are bound at compile time; a string -> proc converter
would need to load the symbol table to determine the function address.
This is O/S dependent. Also, if the symbol table has been striped, it
won't work.
swick@ATHENA.MIT.EDU (Ralph R. Swick) (12/20/89)
You're contradicting yourself. Since one can already bind action proc names to "real functions", why would it be operating system dependent to bind callback names to "real functions?" Go read the manual. There's some extra work to be done, basically to provide an OS-independent symbol table equivalent. Suppose that callbacks could be registered in a fashion similar to action proc registration. That would certainly be one way to implement the String to Callback converter. Anyone who wants is welcome to prototype it...
brianw@gazooch.Sun.COM (Brian Warkentine) (12/20/89)
In article <15040@boulder.Colorado.EDU> grunwald@foobar.colorado.edu writes: >>>>>> On 19 Dec 89 18:45:23 GMT, brianw@gazooch.Sun.COM (Brian Warkentine) said: > >Action procs are bound at compile time; a string -> proc converter >would need to load the symbol table to determine the function address. >This is O/S dependent. Also, if the symbol table has been striped, it >won't work. You missed the point: binding functions (aka "actions procs") to function names is already being done with action procs. What makes doing it with callback procs any more system dependent? You're reading "arbitrary function binding" into what I wrote. I agree, it's not portable. Furthermore, I don't believe this is necessary or even desirable. -brian warkentine brianw@sun.com
marbru@auto-trol.UUCP (Martin Brunecky) (12/20/89)
Writing a String to Callback converter is a trivial thing. Just look at the Intrinsic code for an example. What may NOT be such a trivial thing is making the converter code aware of any callback procedures that the application provides. A simple and portable way to do that are "registration routines". A function called by the application (presumably BEFORE any widgets are created), which hands the callback procedure name(String) and pointer to the converter code (which must implement some sort of callback procedures database - but a simple linked list would work too, unless you want to explore magics of Xrm). Someone may complain that using registeration routines is not very elegant. But since a programmer has to write most of his callbacks, one registration call per callback seems fair to me. For really elegant solution, you need systems which support runtime binding, such as Apollo Aegis, OS/2 - and you can do it even with VMS, and may be (I haven't tried it) with Sun OS. Your application must be shareable image, VMS gives you LIB$FIND_IMAGE_SYMBOL which does exactly what we want - finds a pointer to a named function/procedure. The same thing must be possible on Sun - and may be it's out there, forgive my ignorance. -- ############################################################################### Martin Brunecky, Auto-trol Technology Corporation, 12500 North Washington Street, Denver, CO-80241-2404 (303) 252-2499 ncar!ico!auto-trol!marbru
gary@CTC.CONTEL.COM (Gary Bisaga x4219) (12/21/89)
Martin Brunecky writes: > Someone may complain that using registeration routines is not very elegant. > But since a programmer has to write most of his callbacks, one registration > call per callback seems fair to me. The problem here, of course, is not only that the programmer must write a second function as an "initialization" for the callback registration, but also that this function must be called essentially automatically at process startup time. This type of thing is a pain to remember, especially when there are multiple programmers and many such functions -- it's exceedingly easy to forget to do consistently. With C++, there is a simple and automatic way of doing this. Define a class called, for example, XXX as follows: class XXX { int dummy; public: XXX(void (*callbackFunction)(), char *registrationName) {registerCallback(callbackFunction, registrationName);} }; The registerCallback function, invoked from the constructor, should make an entry into a table (linked list, hashed table, fill in the blank) registering the connection between the function and string. Then define a macro DEFINE_CALLBACK which calls the XXX constructor as follows: #define DEFINE_CALLBACK(functionName) \ void functionName(); \ static class XXX functionName_Callback(functionName, "functionName"); \ void functionName Every function which must be registered as a callback should be defined using the DEFINE_CALLBACK macro. Usage is as follows: DEFINE_CALLBACK(MyCallbackFunc)(int firstArg, void *secondArg) { ... } This works, of course, because of C++'s automatic calls to constructors at the beginning of the scope of the variable, which in this case is process startup. Gary Bisaga (gary@ctc.contel.com)