Callbacks


Callbacks
A Callback is a function that is executed through a pointer. Instead of the pointer containing the address of some data it contains the address of a function. If you are unfamiliar with function pointers just keep in mind that they are a variable, that when assigned the address of a function can be used as if it were the function itself. For example, if I had a function pointer called foo and assigned it the address of a function called bar, I could use it as if it were bar:

int bar(int i) { return i; }

void somefunc()
{
        int val;
        int (*foo)(int);

        foo = &bar;

        val = foo(3);   // val == 3
        val = bar(4);   // val == 4
}
If the above is at all confusing you should probably brush up on function pointers in a good C book before going on, however if you use the macros provided by messiahAPI and follow the conventions laid out in these docs and accompanying example projects, then you will probably never even realize that you are using Callbacks.
Declaring Function Pointers
messiahAPI provides a macro called FX_API() that is used to declare a function pointer, in fact all of the API functions are wrapped in this macro (check out any of the headers). For example the function fxInitAction() is wrapped up like so:
FX_API(FXint, fxInitAction)(FXint action_module);
This expands to the following:
// If _MAINPLUGIN_FILE is defined
FXint (*fxInitAction)(FXint action_module);
// If _MAINPLUGIN_FILE is not defined
extern FXint (*fxInitAction)(FXint action_module);
// If __cplusplus is defined
extern "C" FXint (*fxInitAction)(FXint action_module);
The only time you will need to create function pointers is when you are Publishing Function Modules for use by other plugins. It will be necessary then for you to provide a header file, that is not unlike messiahAPI header files, to any other developers using your library. See Publishing Function Modules for more details.
Callback Signature Macros
Often you will need to provide messiah with a Callback of your own. For example an Access Based Module will need to provide messiah with the address of a function to which it can pass notification messages. To help in this process messiahAPI provides macros for each type of Callback that you might need to create. These macros are referred to as Callback Signature Macros. As an example, to declare and define a function to handle notification messages we would use FX_ACCESSFUNC():

// Declare function
FX_ACCESSFUNC(MyCallback);      

// ...

// Define function
FX_ACCESSFUNC(MyCallback)
{
        // ...
}
The macro FX_ACCESSFUNC(MyCallback) expands to the signature of the function, with MyCallback as its name. Because you are not hard coding the arguments and return type of the function, your code is shielded from changes made to messiahAPI. It is strongly recommended that you use Callback Signature Macros wherever provided.
Callback Types
For convienence we have given names to the types of Callbacks that you might need to provide to messiah. For example, the function that will handle notification messages for an Access Based Module is called access_func(). This is purely for notational purposes in these docs, it allows us to talk about any Callback that acts as a handler for Access Notification messages. Since those Callbacks will be defined using the Callback Signature Macros we can say that an access_func() is any Callback that you declare and define using the FX_ACCESSFUNC() macro.
Following is a list of all Callback Types and their associated Callback Signature Macros:
access_func() FX_ACCESSFUNC() Called by messiah to handle Access Notifications
entry_func() FX_ENTRYFUNC() Called by access_func() to handle Access Notifications
exp_func() FX_EXPFUNC() Called by messiah to execute Function Module
shader_func() FX_SHADEREVALUATE() Called by messiah to evaluate a Shader Module
shader_init_func() FX_SHADERINITINPUTS() Called by messiah to initialize a Shader Module
control_func() FX_CONCALLBACK() Called by messiah to inform a Module of events associated with a its controls
scan_func() FX_EFFECTSCAN() Called indirectly by plugin to enumerate an Effect's targets
disp_func() FX_DISPLACESCAN() Called indirectly by plugin to enumerate an Object's points for displacement
hierarchy_func() FX_HIERARCHYSCAN() Called indirectly by plugin to enumerate an Object hierarchy
Enumeration Callbacks
Some of the Callbacks that you'll create will be used for iterating over a sequence of items. Examples of Enumeration Callbacks are scan_func(), disp_func() and hierarchy_func(). These Callbacks operate very similarly to the "compare" callback that you pass to the C Standard Library function "qsort()". That is you will call a messiah function passing it the address of your Callback, then messiah will immediatly procede to call your Callback once for each item in a particular sequence.
For example, when you are displacing the points of an object in an Effect Module you could cycle through all of the points using fxMeshPoint(), or you could call fxDisplaceScan() and pass it your disp_func() Callback's address. Your disp_func() will get called once for each point in the mesh. This has the added bonus that most of the information you'll need for each of the points is passed in an FX_DisplacePoint_St struct.
All of the Enumeration Callbacks allow you to pass yourself some data that you create. Put another way, when you start the enumeration, you can pass some data that messiah will in turn pass to your Enumeration Callback each time that it is called. The reason for this is efficency. For example let's say that there is some value that only needs to be calculated once, independent of the current item being enumerated. It would be very inefficent for us to calculate it in our Enumeration Callback because we would be calculating it once for each item. Instead if we could calculate it once, then pass it to our Enumeration Callback we would keep things efficent and have that value available to us in our Callback.
We are able to do this by passing the address of our value to the messiahAPI function we use to start the enumeration process. That address will in turn be passed to our Enumeration Callback. As far as messiah is concerned this address is a FXvoid *, so we would have to cast it to whatever data type it really is inside of our Callback. However if you look at what the Enumeration Callback's Callback Signature Macro expands to, you will notice that the second argument becomes the data type for the last argument in the Callback, and the thrid argument becomes the name of that variable. You will also notice that this becomes a pointer to that data type.
A very typical use for this is to pass an Effect Module's state data to the Enumeration Callback: scan_func(). We get the state data by calling fxObjectGetTypeData() ( see Data Attachment for more info ), we don't want to do this each time our scan_func() gets called because the address of this data doesn't change between calls, so why add the overhead? Instead we'll get the address of the state data before starting the target enumeration, then pass that address to fxEffectTargetScan() to start the enumeration.
Example:

// get state data from the effect
MyEffectData *med = fxObjectGetTypeData( effect, FX_NOFLAG );

// start the target enumeration 
// with med being passed to each call of our callback
fxEffectTargetScan( effect, MyScanFunc, med, FX_NOFLAG );

// ...

// Our target enumeration callback ( scan_func() )
FX_EFFECTSCAN( MyScanFunc, MyEffectData, theData )
{
        // now theData is a MyEffectData * that points to
        // our effect's state data, neat huh?

        // displace points
        // ...

        return FX_TRUE;
}


© 2003 pmG WorldWide, LLC.


www.projectmessiah.com

groups.yahoo.com/pmGmessiah

Last Updated on Thu Jul 10 04:49:36 2003