[comp.lang.c] An array of function pointers.

jantypas@ucrmath.UUCP (John Antypas) (09/15/88)

This may seem like a simple question but I've no luck with an answer so 
perhaps the net could help.  

In a graphics application we're writing at work, we have several functions for 
drawing lines, circles etc.  We'd like to set up something like a vector table.
If the vector table has a NULL in a spot, then the interpreter will use its
internal routines instead of faster device specific code.  As an example:

vectors[] =	{ dev_line(),
		  dev_box(),
		  dev_circle(),
		  dev_arc(),
		  dev_text()
		}

This says we have device specific code for all five functions.  Yet when I 
try to copy function addresses, the compiler complains.  How do I get the
address of a funciton and put it into an array for calling later?

Thanks.

John Antypas -- Soft21 --21st Century Software:
UUCP: {crash, garp, killer, pyramid, reed, ucsd!ucrmath}!soft21!jantypas
Internet: jantypas%soft21.uucp@{garp.MIT.EDU, ucsd.EDU}
Domains:  jantypas@{soft21.Riverside.CA.US, soft21.CTS.COM}

steve@oakhill.UUCP (steve) (09/16/88)

I'm sorry for clogging the newsgroup with this reply, but my Email keeps
bouncing back.

In article <414@ucrmath.UUCP>, jantypas@ucrmath.UUCP (John Antypas) writes:
> This may seem like a simple question but I've no luck with an answer so 
> perhaps the net could help.  
> 
> In a graphics application we're writing at work, we have several functions for 
> drawing lines, circles etc.  We'd like to set up something like a vector table.
> If the vector table has a NULL in a spot, then the interpreter will use its
> internal routines instead of faster device specific code.  As an example:
> 
> vectors[] =	{ dev_line(),
> 		  dev_box(),
> 		  dev_circle(),
> 		  dev_arc(),
> 		  dev_text()
> 		}
> 
> This says we have device specific code for all five functions.  Yet when I 
> try to copy function addresses, the compiler complains.  How do I get the
> address of a funciton and put it into an array for calling later?
> 
> Thanks.
> 
> John Antypas -- Soft21 --21st Century Software:
> UUCP: {crash, garp, killer, pyramid, reed, ucsd!ucrmath}!soft21!jantypas
> Internet: jantypas%soft21.uucp@{garp.MIT.EDU, ucsd.EDU}
> Domains:  jantypas@{soft21.Riverside.CA.US, soft21.CTS.COM}

I have some function array code I took from another source a while back.
It works and it shows some of the ways and uses this sort of thing is
usefull for.  Please feel free to use any part of it.  Of course I've
simplified it for you.

--------------------------START OF CODE------------------------------
#define COMMAND_LIST      1
#define COMMAND_ADD       2
#define COMMAND_QUIT      3
#define COMMAND_HELP      4
#define COMMAND_SHOW      5
   
char buffer[150];
char *buffer_place;

struct command_info
    {
    char *name;
    short significant;
    int number;
    void (*function)();
    };

void command_add(),command_help(),command_list(),command_show();

struct command_info command_table[] = {
    { "add",    1,  COMMAND_ADD,   command_add   },
    { "help",   1,  COMMAND_HELP,  command_help  },
    { "list",   1,  COMMAND_LIST,  command_list  },
    { "quit",   1,  COMMAND_QUIT,  NULL          },
    { "show",   1,  COMMAND_SHOW,  command_show  },
    { NULL,     0,  0,             NULL          }};

void run_commands()
    {
    boolean more;
    struct command_info *this_command;
    int linelength;

    more = YES;
    while (more)
        {
        printf("Command : ");
        linelength = readline(stdin,YES);
        if (linelength)
            {
            this_command = get_command(command_table);
            if (this_command->function)
                (*this_command->function)();
            else if (this_command->number == COMMAND_QUIT)
                more = NO;
            else
                {
                printf("Unknown or ambiguious command not understood.\n");
                printf("Type Help for help\n");
                }
            }
        }
    return;
    }

struct command_info *get_command(command_table)
    struct command_info *command_table;

    {
    struct command_info *this_command;
    int count;
    char *this_c;
    boolean more;
    boolean somemore;
    boolean good;

    this_command = command_table;
    more = YES;
    while (this_command->name && more)
        {
        count = 0;
        this_c = this_command->name;
        buffer_place = buffer;
        good = YES;
        somemore = YES;
        while (good && somemore)
            {
            if (*this_c && *buffer_place && *buffer_place != ' ')
                {
                if (*this_c == *buffer_place)
                    {
                    count++;
                    this_c++;
                    buffer_place++;
                    }
                else
                    good = NO;
                }
            else if (*buffer_place && *buffer_place != ' ')
                good = NO;
            else
                somemore = NO;
            }
        if (count >= this_command->significant && good)
            more = NO;
        else
            this_command++;
        }
    return(this_command);
    }
-----------------------------END OF CODE------------------------------


                   enough from this mooncalf - Steven
----------------------------------------------------------------------------
These opinions aren't necessarily Motorola's or Remora's - but I'd like to
think we share some common views.
----------------------------------------------------------------------------
Steven R Weintraub                        cs.utexas.edu!oakhill!devsys!steve
Motorola Inc.  Austin, Texas 
(512) 440-3023 (office) (512) 453-6953 (home)
----------------------------------------------------------------------------

gwyn@smoke.ARPA (Doug Gwyn ) (09/16/88)

In article <414@ucrmath.UUCP> jantypas@ucrmath.UUCP (John Antypas) writes:
>try to copy function addresses, the compiler complains.  How do I get the
>address of a funciton and put it into an array for calling later?

Just use the name of the (previously declared) function; that IS
a pointer to the function.  Note that all the function pointers in
your array should have the same type, which means that all the
functions themselves should have the same type.  (Also of course
the array needs to be declared as an array of pointers to functions
having that type.)

nate@altos86.UUCP (Nathaniel Ingersoll) (09/21/88)

In article <414@ucrmath.UUCP> jantypas@ucrmath.UUCP (John Antypas) writes:
 >drawing lines, circles etc.  We'd like to set up something like a vector table.
 >If the vector table has a NULL in a spot, then the interpreter will use its
 >internal routines instead of faster device specific code.  As an example:
 >
 >vectors[] =	{ dev_line(),
 >		  dev_box(),
 >		  dev_circle(),
 >		  dev_arc(),
 >		  dev_text()
 >		}
 >
 >Thanks.
 >
 >John Antypas -- Soft21 --21st Century Software:
 
 I often have programs where I look up a function based on
 something like user input, and what I usually do is
 similar to:
	/* hjkl character movement ... */

	int	f_left(), f_right(), f_up(), f_down();

	int (*vectors[0200])();

	init_vec() {
		vectors['h'] = f_left;
		vectors['j'] = f_down;
		vectors['k'] = f_up;
		vectors['l'] = f_right;
	}


or, similarly,

#define		CASE1	0
#define		CASE2	1
...
#define		CASEN	N	/* some N */

where some input function returns a CASEx, and then
you can have an array of function pointers like

int (*vectors[how many])() = {
	f_case1,
	f_case2,
	...
};

and go like

	int whatcase, getcase();
	int (*f)(), invalidcase();

	whatcase = getcase();
	if (whatcase >= 0 && whatcase < MAXCASE)
		f = vectors[whatcase];
	else
		f = invalidcase;
	(*f)(...);



Now that I've beaten this to death, good luck.
-- 
Nathaniel Ingersoll
Altos Computer Systems, SJ CA
	...!ucbvax!sun!altos86!nate
	altos86!nate@sun.com

english@panarea.usc.edu (Joe English) (09/22/88)

In article <414@ucrmath.UUCP> jantypas@ucrmath.UUCP (John Antypas) writes:
>We'd like to set up something like a vector table.
>If the vector table has a NULL in a spot, then the interpreter will use its
>internal routines instead of faster device specific code.  As an example:
>
>vectors[] =	{ dev_line(),
>		  dev_box(),
>		  dev_circle(),
>		  dev_arc(),
>		  dev_text()
>		}
>
>[...] ... when I 
>try to copy function addresses, the compiler complains.  How do I get the
>address of a funciton and put it into an array for calling later?

This works, (and it's an excellent way to set up a device driver, I
might add.)  The only problem with the initialization is that you're
using function _call_ syntax, which can't be evaluated at compile
time.  If you declare the functions (int dev_line(), dev_box(),...;)
beforehand, you can write:

int (*vectors)()[] = { dev_line, 
                       dev_box,
                       ...
                     }

_without_ parentheses; this evaluates to the address of the function,
which can be initialized, instead of a function call.

      /|/| Joe English
-----< | | ARPA: english%lipari@oberon.usc.edu
  O   \|\|