[comp.sys.mac.programmer] Objects in Code Resources - HELP!

potts@itl.itd.umich.edu (Paul Potts) (05/22/91)

Help!

I have been working with an object library for handling sounds,
written in THINK C with object extensions (but not the Class
Library).

The first object, called CDispatcher, creates the data
structures and other objects in the chain. CDispatcher gets
passed strings, which it breaks up, tokenizes, and uses
to call the other objects in the heirarchy.

It all works great, when these objects are built into an
application, with a simple front end that uses the C console
window to ask for commands and pass them to CDispatcher.
I've been doing this, though, in the hopes that I could
eventually use this object heirarchy in an XCMD/XFCN setting.

I converted the project to create a code resource of type
XFCN, changed ANSI to ANSI-A4, OOP to OOP-A4, etc. I *think*
that I've done the obvious things. I've built XCMDs and
XFCNs before, though it has been awhile, and I've never
tried one so elaborate. It is a large code resource, but
still fits in a single segment, even though I have to check
"Multi-Segment Code Resource" or the compiler complains.

Below is the trial "front end" I gave my object heirarchy
when I am compiled it as a code resource. Note that I
am only including the first part of the file to save space.

When I call my code resource from Hypercard, doing
something like "put SoundPackage(OpenChannel, sampledSynth)
into card field blah...", my MAIN gets called, the param
block seems to be setup the way it should be, the first
Debugger() line gets called, the second Debugger() line
gets called, and then... BLOOEY!

Right at the first object call,

    myDispatcher->Init

I get a System Error ID = 28. It is happening in a JSR
call, to somehwere inside my code resource.

I'll try to get a Disassembler and track down what it
is doing, but in the meantime, does anyone have any ideas?
Are there any special things to watch out for when using
objects in code resources?

Thanks in advance,

-Paul-
potts@itl.itd.umich.edu

#include <pascal.h>
#include <oops.h>
#include <HyperXCmd.h>
#include <stdio.h>
#include "CDispatcher.h"

SoundErrorPtr	result;

Handle CopyStrToHand(str)
/* borrowed from Gary Bond */
		char* str;
{
	Handle newHndl;
	newHndl = (Handle) NewHandle ((long) strlen(str) + 1);
	strcpy ((char*)(*newHndl), str);
	return (newHndl);
}



pascal void main (XCmdPtr paramPtr);

pascal void main (paramPtr)
	XCmdPtr	paramPtr;
	
{
	Str255			incoming, reply;
	static			CDispatcher		*myDispatcher;
	extern 			SoundErrorPtr 	result;
	
	Debugger();
	myDispatcher = new (CDispatcher);
	Debugger();
		myDispatcher->Init();
	/* create the first object in the chain 
			and tell it that it has been made */

	Debugger();
	if (paramPtr->paramCount == 1)
	{
		Debugger(); 

		HLock(paramPtr->params[0]);
		strcpy((char*)incoming, (*(paramPtr->params[0]))); 
		HUnlock(paramPtr->params[0]);

		Debugger(); 
			


Here is the assembly code generated by the first few lines of the above program.
A System error 28 occurs in the call to JSR $4808(A4).  Since it immediately
follows the second Debugger() call, I think this corresponds to the first
message-passing.

  MAIN
     +0000  0053B7B6   LINK       A6,#$FE00                     
     +0004  0053B7BA   _Debugger                             ; A9FF       
     +0006  0053B7BC   PEA        $47F2(A4)                               
     +000A  0053B7C0   JSR        'XFCN 0032 0874 SounI+4566 ; 0053BC5A   
     +000E  0053B7C4   ADDQ.L     #$4,A7                                  
     +0010  0053B7C6   MOVE.L     D0,$57FC(A4)                            
     +0014  0053B7CA   _Debugger                             ; A9FF       
     +0016  0053B7CC  *MOVE.L     $57FC(A4),-(A7)                      

/* CRASHING WITH AN ID=28 at the very next instruction */
   
     +001A  0053B7D0   JSR        $4808(A4)                               
     +001E  0053B7D4   ADDQ.L     #$4,A7                                  
     +0020  0053B7D6   _Debugger                             ; A9FF       
     +0022  0053B7D8   MOVEA.L    $0008(A6),A0                            
     +0026  0053B7DC   CMPI.W     #$0001,(A0)                             
     +002A  0053B7E0   BNE        MAIN+00AA                  ; 0053B860   
     +002E  0053B7E4   _Debugger                             ; A9FF       

Eric.J.Baumgartner@dartmouth.edu (Eric J. Baumgartner) (05/23/91)

In article <1991May22.011618.27337@terminator.cc.umich.edu>
potts@itl.itd.umich.edu (Paul Potts) writes:

> It all works great, when these objects are built into an
> application, with a simple front end that uses the C console
> window to ask for commands and pass them to CDispatcher.
> I've been doing this, though, in the hopes that I could
> eventually use this object heirarchy in an XCMD/XFCN setting.

I'm using oops in a THINK C XCMD and there are definitely a couple of
tricks; I think I've solved them.

First off, the XCMD has to be multi-segment to use oops.  This isn't
really a big deal until your HC users decide to copy it into their
stack... then they'll probably forget the CCOD resource.  (THINK C
creates 1 XCMD resource and as many CCOD resources as are necessary,
and I assume the ID's of both the XCMD and the CCOD are important and
shouldn't be changed.)  So be sure to warn 'em.

That's multi-segment.  The other thing you've gotta do is the old
"preserve A4" trick, like you used to do to use strings in THINK C 3.x,
because when you go multi-segment, THINK starts storing strings as
globals again.  (p. 87 in the manual)  (The method table is probably
tucked away like the strings as well, so you need to save A4 to access
those values too.  Symantec people, please correct me as needed.)

So my main routine looks like this:

#include <SetUpA4.h>
#include <HyperXCmd.h>

pascal void main(XCmdPtr paramPtr)
{
	RememberA0();
	SetUpA4();
	
 /* Do your stuff here.  This is a xwindow for HC 2.x, so
    paramCount may be negative. */

	if (paramPtr->paramCount == -1) {
		DoMacEvent(paramPtr);
	} else if (paramPtr->paramCount > -1) {
		DoFirstTime(paramPtr);
	}

	/*	We're multi-segment, so be careful. */
	/*UnloadA4Seg(0L);*/	/*	If HC tries to keep us around, this is a bad
thing. */
							/*	Maybe jump dump the CCOD resource??? */
	RestoreA4();
}

So you set up A4 prior to doing anything else, and restore it at the
end, and you're fine.  Your object files and method calls don't need to
worry about A4 at all.

The THINK manual mentions (p. 91) that you've got to unload additional
segments yourself, but I left the call commented out because I'm
trusting HyperCard to manage the resources.  This may be a bad thing;
I'm not sure, but nothing's broken yet, so I'm not going to change...
but if anyone knows for sure whether I should uncomment the UnloadA4Seg
call, I'd appreciate a note.

Hope this helps.

Eric Baumgartner                   *  ebaum@dartmouth.edu
Interactive Media Lab              *  - When in danger or in doubt,
Dartmouth Medical School           *      run in circles, scream and
shout.

francis@arthur.uchicago.edu (Francis Stracke) (05/23/91)

In article <1991May22.173738.6863@dartvax.dartmouth.edu> Eric.J.Baumgartner@dartmouth.edu (Eric J. Baumgartner) writes:

>First off, the XCMD has to be multi-segment to use oops.  This isn't
>really a big deal until your HC users decide to copy it into their
>stack... then they'll probably forget the CCOD resource.  (THINK C
>creates 1 XCMD resource and as many CCOD resources as are necessary,
>and I assume the ID's of both the XCMD and the CCOD are important and
>shouldn't be changed.)  So be sure to warn 'em.

Or distribute it in a HC stack, with an "install" button, so they
don't need to worry about it.  :-)

--
/============================================================================\
| Francis Stracke	       | My opinions are my own.  I don't steal them.|
| Department of Mathematics    |=============================================|
| University of Chicago	       | Earth: Love it or leave it.	     	     |
| francis@zaphod.uchicago.edu  |  					     |
\============================================================================/