moore@cs.washington.edu (Charles Moore) (07/06/90)
Is a call to PasToZero necessary in order to return a result to Hypercard from an XCMD? The appendix to the HyperCard Script Language Guide is pretty cagey about this saying only that the returnValue field of the XCmdBlock can contain a handle to a zero-terminated string. But where is the space for this string allocated? I allocated space within my XCMD with the declaration: char resultStr[80]; and then tried to return this value with the assignment: paramPtr->returnValue = (Handle)&resultStr; The result was a system error. Does this mean that PasToZero, in addition to converting between string types, also commands HyperCard to allocate space for the converted string? If so, why must I use PasToZero? I already have a zero-terminated string. I don't need to convert it; I just need to return it. Where is the glue routine that has HyperCard allocate some space and copies your string into that space but that doesn't waste time doing unnecessary conversions? Charles Moore
gb2a+@andrew.cmu.edu (George J. Baxter) (07/06/90)
I think you should be using ZerotoPas.. This is if you're programming in 'C' or something.. and you have to convert your zero terminated string to a Pascal string so that Hypercard, which is written in Pascal, can read it. It would also explain the system error.
mcguire@cs.utexas.edu (Tommy Marcus McGuire) (07/07/90)
I believe that PasToZero does allocate the space for the handle and the string for returnValue. Your problem might be with the char resultStr[80]; declaration. Doesn't the space allocated for the string itself go away when your XCMD returns? Rather than calling PasToZero, though, you could allocate the space for the string on the heap yourself. Tommy McGuire
gibson@tut.cis.ohio-state.edu (William Kerr Gibson) (07/09/90)
In article <12477@june.cs.washington.edu> moore@cs.washington.edu (Charles Moore) writes: >Is a call to PasToZero necessary in order to return a result to Hypercard >from an XCMD? The appendix to the HyperCard Script Language Guide is ... >is the space for this string allocated? I allocated space within my >XCMD with the declaration: > >char resultStr[80]; > >and then tried to return this value with the assignment: > >paramPtr->returnValue = (Handle)&resultStr; > >The result was a system error. Does this mean that PasToZero, in ... > >Charles Moore Howdy, my name is seann i am Kerr's brother. You have a couple of problems here: 1st, I assume that you have declared resultStr in your main as one of the local variables. This means that the 80 bytes of space that you have declared are on the Stack; thus when you return to hypercard, you have NO GAURANTEE at all with what hypercard will do to the stack, and since hypercard does not know that this result parameter is on the stack, it could easily overwrite this area. As a general RULE, NEVER return a pointer to anything that you have declared as local storage in a 'c' function. Your second problem, and perhaps a worse one is that you HAVE NOT returned a handle at all! what you have returned is merely a pointer. In fact, you have not really even returned a pointer to a pointer, which is as i believe, what you are trying to return. Because, since resultStr is on the stack (the space is on the stack) refering to resultStr without any brackets [] is the same as refering to &resultStr. in other words: char resultStr[80]; char *a; a = resultStr; is the same as... a = &resultStr; but at any rate even if you do return a pointer to a pointer this will NOT help you at all because a pointer to a pointer is NOT the same as a handle. A handle will be explicitly declared as such in hypercards heap zone so that it knows the size and can move it around and compact the heap and do whatever it likes. In other words, paramPtr-> returnValue is a space of 4 bytes and you have put 4 bytes in there that happen to be a pointer to a group of 80 bytes. now when hypercard tries to dispose of this handle or set the size different, or do any memory operations with it, the results are unpredictable, and could easily destroy hypercards heap which will eventually cause any number of system errors to occur. and now my brother (the hypercard XCMD whizz boy) will tell you what you should really do... sorry Charlie, but you are going to have to declare a handle somewhere. Fortunately this is not too difficult. When you use paramPtr->returnValue you have two options. 1. you can assign paramPtr->returnValue to an existing handle (much like you have tried to do in your code). In this case you need to have actually declared space for your handle with NewHandle(). Once you have assigned returnValue you must NOT dispose of the old handle as HyperCard will dispose of it for you. E.g. { Handle resultStr; resultStr = NewHandle((long) 80); /* declare space for the handle */ ... strcpy(*resultStr,"This is my return message"); /* perform string operations */ ... paramPtr->returnValue = resultStr; /* returnValue is now same as resultStr */ /* WARNING! Do not dispose of resultStr. Hypercard will dispose of */ /* paramPtr->returnValue on its own, which amounts to the same thing */ return(); } 2. The other thing you can do is to declare space for returnValue at the time you assign your string to it. { char resultStr[80]; ... paramPtr->returnValue = CopyStrToHand(resultStr); return(); } /* CopyStrToHand function is below */ /* This is taken from "XCMD's For HyperCard" by Gary Bond */ Handle CopyStrToHand(str) char *str; { Handle newHndl; newHndl = (Handle) NewHandle((long) strlen(str) + 1); strcpy((char *) (*newHndl), str); return(newHndl); } That's it.... Hope this helps you out! Kerr Gibson CIS Dept OSU. (614)292-0915 __---------------------__ gibson@tut.cis.ohio-state.edu _____________ / >------------------- att-cb!osu-cis!tut.cis.oh...!gibson `-~~~~~~~~~"--'---/ / OSU 2036 neil av. Col. Oh. 43210-1277 `---`==________/ Engage!
stm@apple.com (Steve Maller) (07/10/90)
The name "PasToZero" is misleading. It should be PasToZeroHandle. It allocates the space necessary and returns a regular Memory Manager Handle to a null-terminated string. You can roll your own version of it, but you have to go through the memory manager. I yam what I yam...