mirror of
https://github.com/ZDoom/qzdoom-gpl.git
synced 2024-11-17 17:50:57 +00:00
01f59fa85f
heavily customized version of DUMB (Dynamic Universal Music Bibliotheque). It has been slightly modified by me: * Added support for Ogg Vorbis-compressed samples in XM files ala FMOD. * Removed excessive mallocs from the replay core. * Rerolled the loops in resample.c. Unrolling them made the object file ~250k large while providing little benefit. Even at ~100k, I think it's still larger than it ought to be, but I'll live with it for now. Other than that, it's essentially the same thing you'd hear in foobar2000, minus some subsong detection features. Release builds of the library look like they might even be slightly faster than FMOD, which is a plus. - Fixed: Timidity::font_add() did not release the file reader it created. - Fixed: The SF2 loader did not free the sample headers in its destructor. SVN r995 (trunk)
113 lines
5.4 KiB
Text
113 lines
5.4 KiB
Text
/* _______ ____ __ ___ ___
|
|
* \ _ \ \ / \ / \ \ / / ' ' '
|
|
* | | \ \ | | || | \/ | . .
|
|
* | | | | | | || ||\ /| |
|
|
* | | | | | | || || \/ | | ' ' '
|
|
* | | | | | | || || | | . .
|
|
* | |_/ / \ \__// || | |
|
|
* /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque
|
|
* / \
|
|
* / . \
|
|
* fnptr.txt - Function pointer explanation. / / \ \
|
|
* | < / \_
|
|
* | \/ /\ /
|
|
* \_ / > /
|
|
* | \ / /
|
|
* | ' /
|
|
* \__/
|
|
*/
|
|
|
|
|
|
C allows you to create and use function pointers. A function pointer is a
|
|
variable that points to a function, and you can use it to call that function.
|
|
Why is this useful?
|
|
|
|
Function pointers can be passed as parameters. As an example, here's a
|
|
function from Allegro:
|
|
|
|
void create_light_table(COLOR_MAP *table, const PALETTE pal, int r, g, b,
|
|
void (*callback)(int pos));
|
|
|
|
Don't worry about the syntax just yet, but the last parameter, 'callback', is
|
|
a pointer to a function that takes an int parameter. create_light_table() can
|
|
take some time to complete its work, and you may want to display a progress
|
|
indicator. So you write a function to draw the progress indicator, and then,
|
|
for 'callback', you specify a pointer to your function. This will enable
|
|
create_light_table() to call your function at intervals during its
|
|
processing. (If you don't want to use the callback, you can pass NULL, but
|
|
this only works because create_light_table() checks actively for NULL. You
|
|
can't always specify NULL when you want nothing to happen.)
|
|
|
|
There are many other uses. In addition to using function pointers as
|
|
parameters, Allegro has some global function pointers you can set to point to
|
|
your functions. Function pointers can also be used in structs, and this is
|
|
where DUMB makes the most use of them.
|
|
|
|
So how are they used?
|
|
|
|
void bar(void) { ... } /* Here's a function */
|
|
void (*foo)(void) = &bar; /* Take a pointer */
|
|
(*foo)(); /* Call the function */
|
|
|
|
char *baz(float a) { ... } /* Here's another function */
|
|
char *(*foobarbaz)(float a) = &baz; /* Take a pointer */
|
|
char *rv = (*foobarbaz)(0.1); /* Call the function */
|
|
|
|
In both these cases, note how the statement for calling the pointed-to
|
|
function (third line) resembles the definition of the function pointer
|
|
(second line). This is true of any variable in C, and can lead to some truly
|
|
obfuscated definitions if you are that way inclined. Such definitions can be
|
|
clarified with typedefs, but before you use those, it is important you
|
|
understand how the above statements work. I speak from experience: function
|
|
pointer notation looks random and scary, until you understand why it's the
|
|
way it is; then it makes perfect sense.
|
|
|
|
(It is actually permissible to omit the & when taking a pointer and to write
|
|
e.g. foobarbaz(0.1) instead of (*foobarbaz)(0.1). However, I recommend not
|
|
doing this, since the syntax for using the pointer no longer resembles the
|
|
definition. Writing e.g. (*foobarbaz)(0.1) also makes a clear distinction
|
|
between function pointer calls and ordinary function calls, which makes code
|
|
more readable.)
|
|
|
|
Note that function pointers have the return value and parameter list
|
|
specified. A function pointer can only point to a function with a matching
|
|
return value and matching parameters. (You can break this rule by casting the
|
|
pointer explicitly, but there is no situation where doing so is portable to
|
|
all computers, and I strongly advise against it unless you're writing system
|
|
code. If you're not sure whether you're writing system code or not, then
|
|
you're not.)
|
|
|
|
The parameter names need not match (although the types must). If you wish to
|
|
rename a parameter in your function, you do not have to change the function
|
|
pointer accordingly. In fact, when you define a function pointer, you don't
|
|
even have to specify the names of parameters if you don't want to. I normally
|
|
do so for clarity.
|
|
|
|
It is possible to typedef a function pointer. In order to typedef a function
|
|
pointer, you start by declaring the pointer as a variable:
|
|
|
|
void (*myfunc)(void);
|
|
|
|
Then you write 'typedef' before it and replace the variable name, which is
|
|
myfunc, with the type name (this rule can be applied to any variable when you
|
|
want to use typedef):
|
|
|
|
typedef void (*MYTYPE)(void);
|
|
|
|
Now 'MYTYPE' represents a pointer to a function with no parameters and no
|
|
return value. The following two lines are completely equivalent:
|
|
|
|
MYTYPE myfunc;
|
|
void (*myfunc)(void);
|
|
|
|
Note that we use MYTYPE without an asterisk (*), since it is already a
|
|
pointer.
|
|
|
|
That's it. If you feel anything should be explained better here, or if you
|
|
feel something should be added, please don't hesitate to let me know!
|
|
|
|
|
|
Ben Davis
|
|
entheh@users.sf.net
|
|
IRC EFnet #dumb
|
|
See readme.txt for details on using IRC.
|