taylorj@yvax.byu.edu (07/27/90)
I think there's a lot of confusion about globals in XCMDs. I will attempt to cast some light on the subject from my limited knowledge, and perhaps others can either amplify or correct... As I understand it, there are two completely different meanings for the term "global". 1) Variables that can be accessed by more than one function or procedure. I would also lump C's static variables in this category. 2) Persistent variables that "stick around" between calls from HyperCard to the XCMD. It's very easy to work with the first type of global variables in either C or Pascal (contrary to popular belief and quite a number of manuals). I use SetupA4 in Think C 3.0 and can happily use all the global and static variables that my heart desires, AS LONG AS I don't expect any of these variables to be valid once my XCMD returns control to HyperCard. As far as I know, no language directly supports the second kind: persistent globals. But there are lots of ways to do it yourself. Here are a few... - Store the global data in HyperCard globals. This works quite well and doesn't seem to degrade performance much. - Store the data via a locked handle and return the handle address as the result of the XFCN (to be returned in future calls) or put the handle address in a HyperCard global. This seems to work better for very large amounts of data, as you only have to deal with HyperCard to get the handle instead of the entire amount of data. You also don't have to worry about HyperCard messing up complex data structures. - Store the global data in a resource. It may help to think of calling an XCMD as similar to running a program. For example, you expect an application to use global variables, but you would never expect to run it one day then run it again the next day and still be able to access the data for those global variables. You can likewise think of persistent global variables as similar to preferences, which must be stored in resources or a file in the System Folder in order to stick around between uses of an application. Please correct me if any of this is wrong or unclear. Jim Taylor Microcomputer Support for Curriculum | Brigham Young University | Bitnet: taylorj@byuvax.bitnet 101 HRCB, Provo, UT 84602 | Internet: taylorj@yvax.byu.edu
bc@Apple.COM (bill coderre) (08/04/90)
In article <1425taylorj@yvax.byu.edu> taylorj@yvax.byu.edu writes: |As far as I know, no language directly supports the second kind: persistent |globals. But there are lots of ways to do it yourself. Here are a few... A good mechanism for variables which are persistent across XCMD calls but not across program runs can be gleaned from how many device drivers are written. Basically, you need 3 or 5 calls (the optional ones are in parens): fooINIT -- takes no argument, returns a handle (fooWARMUP) -- "gets ready" to do work fooGO -- does some quantum of work (fooWRAPUP) -- stop doing work fooDIE -- go away now INIT should create a handle, stuff whatever constants or whatnot in it, and return it. The Hypercard program is responsible for keeping the handle around, and sending it with EACH of the calls below. WARMUP should do whatever is needed to prepare to do work without actually doing it. In a printer driver, this would be to allocate the port, send setup codes, etc. On a screen saver, this would be to turn the screen black and set up an interrupt routine to check for events. GO does a small amount of work, such as printing a little text or drawing a few stars on the black screen. WRAPUP takes care of shutting the job down, such as padding and flushing the buffe and closing the port, or sending a message to the window system to update itself. DIE destroys the handle. If the HC program doesn't call die, it is a fatal error. Obviously, many XCMDs won't need WARMUP and WRAPUP. And there might be different GO commands, to do different things. But the basic ideas of INIT creating a handle before doing any work and DIE deleting it on program exit are the important ones to allow for persistence in many systems.