[comp.sys.mac.programmer] Calling Code resources?

newman@ut-emx.UUCP (Dave Newman) (04/07/89)

Here is another question for the net-gods:  how do you call a
code resource (like an XCMD or whatever) from another piece of
code?  Can it be done from a high-level language?  How might it
be done in Pascal?

Thanks,
>>Dave

austing@Apple.COM (Glenn L. Austin) (04/08/89)

In article <11817@ut-emx.UUCP> newman@ut-emx.UUCP (David Newman) writes:
>Here is another question for the net-gods:  how do you call a
>code resource (like an XCMD or whatever) from another piece of
>code?  Can it be done from a high-level language?  How might it
>be done in Pascal?

In C, it is really *relatively* simple -- all you need to do is create a
function pointer.  In Pascal, however, you need to have an assembly-language
routine to do the actual call.  Basically, in order to call a code resource,
you need to do the following steps:

1) Load the resource into the heap (with your favorite GetResource call)
2) Move the resource high into the heap (with MoveHHi)
3) Lock the resource (with HLock)
4) Dereference the Handle (C: *handle, Pascal: handle^)
5) Assign the dereferenced handle to your function pointer in C.  In Pascal,
   it depends upon the implementation of your assembly language routine.
6) Call the function!

Remember that in C, your function assignment is:
  functionname = (type (*)()) pointer
     or easier yet:
  functionname = (void *) pointer
but your function call is
  (*functionname)()


-----------------------------------------------------------------------------
| Glenn L. Austin             | The nice thing about standards is that      | 
| Apple Computer, Inc.        | there are so many of them to choose from.   | 
| Internet: austing@apple.com |       -Andrew S. Tanenbaum                  |
-----------------------------------------------------------------------------
| All opinions stated above are mine -- who else would want them?           |
-----------------------------------------------------------------------------

han@Apple.COM (Byron Han, wyl E. coyote ) (04/08/89)

In article <28576@apple.Apple.COM> austing@Apple.COM (Glenn L. Austin) writes:
>In article <11817@ut-emx.UUCP> newman@ut-emx.UUCP (David Newman) writes:
>>Here is another question for the net-gods:  how do you call a
>>code resource (like an XCMD or whatever) from another piece of
>>code?  Can it be done from a high-level language?  How might it
>>be done in Pascal?
>
>In C, it is really *relatively* simple -- all you need to do is create a
>function pointer.  In Pascal, however, you need to have an assembly-language
>routine to do the actual call.  Basically, in order to call a code resource,
>you need to do the following steps:
>
>1) Load the resource into the heap (with your favorite GetResource call)
>2) Move the resource high into the heap (with MoveHHi)
>3) Lock the resource (with HLock)
>4) Dereference the Handle (C: *handle, Pascal: handle^)
>5) Assign the dereferenced handle to your function pointer in C.  In Pascal,
>   it depends upon the implementation of your assembly language routine.
>6) Call the function!
>
To wit, if you have a code resource with entry point 
     FUNCTION foom(a, b, c, d, e, f):g
you create a pascal function of the following
    FUNCTION  callfoom(a, b, c, d, e, f, x:LONGINT):g; INLINE $205F,$4E90

To call the code resource, use callfoom instead and pass the dereferenced
handle as the final argument. 

Doing it from assembler makes more sense to me since you have better
control over register saving and assembler is more efficient.  By the
way if you are doing this from assembler, it is a REALLY GOOD IDEA to
save registers...

2. Memory management.  If the code resource has the locked bit set, the
code resource will be loaded as low as possible in memory (via ResrvMem)
so moving it high has no effect.  If the code resource is not locked, and 
you don't plan to use the code resource for a "long" time, you
should explicitly lock it and call MoveHHi prior to that.  And HUnlock it
when done.

If you plan to use the resource for a long period of time and are not
sure if the resource has the locked bit set, you should explictly call
ResrvMem to get it as low as possible in the heap.

+-----------------------------------------------------------------------------+
| Disclaimer: Apple has no connection with my postings.                       |
+-----------------------------------------------------------------------------+ 
Byron Han, Communications Architect      Cereal, anyone?  :-)  A1!
Apple Computer, Inc.                     -------------------------------------
20525 Mariani Ave, MS27Y                 Internet: han@apple.COM
Cupertino, CA 95014                      UUCP:{sun,voder,nsc,decwrl}!apple!han
--------------------------------------   GENIE: BYRONHAN
ATTnet: 408-974-6450   Applelink: HAN1   CompuServe: 72167,1664
------------------------------------------------------------------------------

tim@hoptoad.uucp (Tim Maroney) (04/08/89)

In article <11817@ut-emx.UUCP> newman@ut-emx.UUCP (David Newman) writes:
>
>Here is another question for the net-gods:  how do you call a
>code resource (like an XCMD or whatever) from another piece of
>code?  Can it be done from a high-level language?  How might it
>be done in Pascal?

In Pascal, you're probably going to need to link in some assembly
language or at least include some INLINEs.  In C, as long as the
code resource follows C coding standards, you can do it all in the
high level language.  Get the resource and lock it down first.
You then have a handle.  The handle indicates a pointer.  Take that
pointer and convert it to a function pointer.  Then call the function
pointer.  Here's an example in MPW C:

	void (*f)();
	Handle res = GetResource('code', 1);
	if (res == 0) return;
	HLock(res);
	f = (void (*))*res;
	(*f)(name);

And here's one in Lightspeed C, which seems to have some problems with
casting things to function pointers (actually, K&R seems ambiguous on
the proper syntax, so I guess we can't blame them):

	long (*f)();
	Handle h = GetResource(TheType, TheID);
	if (h) {
		HLock(h);
		BlockMove(h, &f, 4);
		return (*f)(select, TheID, where, h, p, multi, off);
	}
-- 
Tim Maroney, Consultant, Eclectic Software, sun!hoptoad!tim
This message does represent the views of Eclectic Software.

oster@dewey.soe.berkeley.edu (David Phillip Oster) (04/08/89)

In article <6917@hoptoad.uucp> tim@hoptoad.UUCP (Tim Maroney) writes:
>In article <11817@ut-emx.UUCP> newman@ut-emx.UUCP (David Newman) writes:
>>how do you call a code resource from another piece of code?  Can it be
>>done from a high-level language?  How might it be done in Pascal?

>In Pascal, you're probably going to need to link in some assembly
>language or at least include some INLINEs.  

Lightspeed Pascal can call other pascal functions two ways:
1.) Pascal allows the parameter of a function to be a procedure,
something like:

PROCEDURE foo( PROCEDURE a( Integer : b));
    BEGIN
     a(3);
    END;
Check your manuals for the exact syntax.
If you call 

foo(POINTER(GetResource('MDEF', 128)^));
the POINTER() will cast the result of the GetResource()^ to a gerneric
pointer that it is legal to pass to anything.  Once again, watch your
locking, code must be loced before you call it.


>Lightspeed C, seems to have some problems with
>casting things to function pointers (actually, K&R seems ambiguous on
>the proper syntax, so I guess we can't blame them):

I've never had any trouble casting things to function pointer in
lightspeed C. But then, I always use typedefs to keep things simple enough
that I can follow them. Examples:

typedef void (*SubrPtr)();
typedef short (*FuncPtr)();
typedef long (*LFuncPtr)();

void CallC(f, arg)SubPtr f;Integer arg;{
	(*f)(arg);
}

The expression ((SubrPtr) *GetResource('CDEF', 128)) is much easier to
understand than (((*void)()) *GetResource('CDEF', 128)).

But that only covers calling procedures that use the C calling sequence.
If you are calling a function that uses the pascal calling sequence, such
as a MDEF, a WDEF, or a CDEF, you can use the routines defined in teh
Lightspeed C file <Pascal.h>  Note, these functions are not documented in
the new LightSpeed C manual. The function pointer goes _after_ all the
arguments:

	CallPascalL(varCode, win, mesg, param, *GetResource('WDEF', 128));
for example.  Once again, make sure the code resource is locked before
you call it.

Lightspeed Pascal probably also implements these CallPascal() functions. I
don't know if Lightspeed Pascal includes a set of CallC() functions, but
I'd be surprised.

------
To Tim Maroney: great pair of postings about ListManager and the usenet
community.

--- David Phillip Oster            --"No doubt about it, time to get
Arpa: oster@dewey.soe.berkeley.edu --a new signature"
Uucp: {uwvax,decvax}!ucbvax!oster%dewey.soe.berkeley.edu

mnkonar@smallberries.SRC.Honeywell.COM (Murat N. Konar) (04/12/89)

In article <11817@ut-emx.UUCP> newman@ut-emx.UUCP (David Newman) writes:
>
>Here is another question for the net-gods:  how do you call a
>code resource (like an XCMD or whatever) from another piece of
>code?  Can it be done from a high-level language?  How might it
>be done in Pascal?
>
>Thanks,
>>>Dave


This code is from the Jan '89 issue of MacTutor (page 12) and it 
works for me (LSP 2.x)


FUNCTION MyFunction (firstArg: firstType; 
                     secondArg: secondType;
                     VAR thirdArg: thirdType;
                     MyFunctionResource: handle) resultType;

INLINE
  $205F, {MOVE.L (A7)+, A0}  
  $2050, {MOVE.L (A0), A0}
  $4E90; {JSR (A0)       }


Make sure the handle to your code is locked.  This code also works
for procedure calls. Good Luck!

____________________________________________________________________
Have a day. :^|
Murat N. Konar        Honeywell Systems & Research Center, Camden, MN
mnkonar@SRC.honeywell.com (internet) {umn-cs,ems,bthpyd}!srcsip!mnkonar(UUCP)