[futurebasic] Re [X-FB] New syntax for CarbonEvent handlers

Message: < previous - next > : Reply : Subscribe : Cleanse
Home   : March 2004 : Group Archive : Group : All Groups

From: Pete Beaumont <furbies@...>
Date: Tue, 9 Mar 2004 21:03:27 +1100
On Tuesday, March 9, 2004, at 03:23  PM, Robert Purves wrote:

>
> H. Gluender wrote:
>
>>   please tell us something about the "toc"-functionality and the 
>> assembler code line?
>> (I know it's defined in Rntm Appearanc.Incl and it's not an Apple 
>> struct. Your code somehow manages to mimic the FB PROC"label" 
>> function for labeled FNs and perhaps the FB PROC"label" function also 
>> uses a global. Can we mortals know how the FB PROC"label" function is 
>> implemented?)
>
> EnterProc/ExitProc causes the compiler to preface the contained FB 
> code with a "routine descriptor". A RoutineDescriptor has both 
> executable assembler code and data; it is an obsolete mechanism for 
> allowing automatic switching between 68K and PPC code, and we don't 
> need to study any of its content except for one part. Buried inside 
> the RoutineDescriptor is an 8-byte structure, which is accessed by 
> this strange code:
>
>   [proc "WindowBoundsChangingHandler" + _FBprocToProcPtrOffset]


What kind of of strange, sick and twisted mind even knows about this 
stuff

Pete...							(the other one)


:-)



>
> The 8-byte structure is a transition vector (also known as a PowerPC 
> ProcPtr). It specifies the address (4 bytes) of a function, along with 
> an environment variable "Table of Contents", or toc (4 bytes). The 
> called function uses the value of toc to access its global variables. 
> This value gets stored in the processor's register R2, also known as 
> RTOC.  Different modules (such as your app, CarbonLib, QuickTime..) 
> use different values of toc. A call from one module to another -- such 
> as a callback from the system into your app -- must ensure that RTOC 
> is set appropriately.
>
> In a callback, the system calls the address sBoundsChangingUPP, where 
> there is some glue code previously set up by NewEventHandlerUPP.
> The glue code extracts toc from the transition vector, sets RTOC to 
> that value, and calls the address specified in the transition vector, 
> i.e. your FB function code.
>
>
>>  the great advantage of making FNs "Local Mode" isn't possible for 
>> most handlers because they need to access globals.
>
> You can of course remove Local Mode if you want to contaminate your 
> handler routine with global variables. Most handlers can be written 
> without globals. I write Local Mode as an advertisement of purity in 
> heart; such routines can be simply copied in one step from a demo into 
> a project under development, where they will "just work" or maybe 
> "just compile" :-)
>
>
>> Finally, we obviously need to accept another GLOBAL (actually a 
>> pseudo static var), namely sBoundsChangingHandler.
>> BTW, why must it be a GLOBAL?
>
> Both sBoundsChangingUPP and sBoundsChangingHandler must be persistent, 
> so that their contents remain as set by the install routine. They 
> cannot be stack-based local variables, because those are liable to be 
> overwritten by other local fns.  Neither needs to be disposed, as they 
> are initialised on the first call only. These requirements are met in 
> FB by making them globals.
>
> begin globals
> dim as TransitionVector  sBoundsChangingHandler // 'static' var
> dim as proc              sBoundsChangingUPP // 'static' var
> end globals
>
> I like to embed the globals declaration inside the installer routine, 
> so that the installer can be copied from a demo and pasted into a new 
> project, in one step. This also corresponds well with the static 
> variable in C, which is the recommended way for storing an XxxxxUPP:
>
> // initialize once; never dispose
> static EventHandlerUPP  handlerUPP = NewEventHandlerUPP( MyHandler );
>
> In C, the internal details of the transition vector/ProcPtr are done 
> by the compiler and not exposed to the application programmer:
> typedef CALLBACK_API( OSStatus, EventHandlerProcPtr 
> )(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void 
> *inUserData);
>
> In FB, we have to put up with a little more ugliness when we install a 
> callback routine.
>
> Robert P.
>
> --
>