function pointers and functions with various arguments (C)

Started by
7 comments, last by szecs 14 years, 5 months ago
Meaning: is there a way in C to do this for example: FuncPointer = some_func; //some_func(int) FuncPointer = other_func; //other_func(float, float), FuncPointer is the same And if it is possible, how do you use it? FuncPointer(); //?
Advertisement
I dont know if it is possible but you can realize arguments in struct:

struct IntArg { int };
struct FloatArgs { float float };
struct Args { IntArg* pInt; FloatArgs* pFloat; };

MyFuncPtr = func; // func( Args arg )

when you are going to call MyFuncPtr, use ie pInt and pFloat keep NULL
You could create a union that contains both types of function pointers.

If you want to be truly evil you can cast the functions address to a void pointer and then cast it back to the correct type when you want to call it, but beware the evil involved.
I want to use many kind of functions,
but I guess this is simply not the way to go.
I'm building a menu system with minimal programming knowledge.
I guess I'll use lots of global variables instead.

Thanks anyway!

But if you want to pass a variable set of arguments, that would mean that when you call through the function pointer you must know what function it points to so you can pass the correctly formatted arguments.

So why not call the function direct? What exactly are you trying to do?

There are at least two ways of doing this, just so you know your options, but I would recommend you refactor your code so that this kind of unstable solution is avoided.

You could declare a function pointer that accepts a void pointer as an argument and pass in structs that contain data with custom formats:

void (*foo)(void*);

Or you could declare a function pointer that accepts a variable argument list:

void (*foo)(...);

More info on variable argument lists here:
http://www.learncpp.com/cpp-tutorial/714-ellipses-and-why-to-avoid-them/
I want to build a menu with functions attaced to the items. And I don't want to hard code every featurs attached to the items, but simply assign functions in a simple menu initializing function. (Which is simply a list of assignments, so maybe I can introduce some kind of scripting later).

But I guess I will simply use void func(void)
and global variables.

I'm sure you can do a menu without resorting to that kind of thing =)

Here is a psuedo code example using enums and a switch:

struct menuItem{ char* str; int   action;};struct menu{ menuItem* items; int   numItems;};menuItem myMenu1[] ={{"doAction1", MENU_ACTION1},{"doAction2", MENU_ACTION2},{"doAction3", MENU_ACTION3},};menuItem myMenu2[] ={{"doAction4", MENU_ACTION4},{"doAction5", MENU_ACTION5},{"doAction6", MENU_ACTION6},};menu myMenus[] ={ {  myMenu1,  3 }, {  myMenu2,  3 },};void ProcessMenu(){   for (int i=0; i<currentmenu->numItems; i++)   {     if (mouseHit)     {        switch(currentmenu->items)        {           case MENU_ACTION1:           {             //do stuff             break;           }           case MENU_ACTION2:           {             //do stuff             break;           }        }     }   }}


You would need to add positional data for the menu items as well.
Quote:Original post by ElectricVoodoo
Here is a psuedo code example using enums and a switch:

*** Source Snippet Removed ***

You would need to add positional data for the menu items as well.


That doesn't solve the problem, you just push it back to passing data to ProcessMenu(). The switch is good if you want to have one callback for the menu instead of one for each item. The real solution is what you and stephe mentioned earlier. The standard solution to passing generic data to a callback is to have a void pointer as one of its arguments.

/* menu.h */typedef int MenuCallback(void *data);int addMenuItem(const char *name, MenuCallback *callback, void *data);void removeMenuItem(int menuID);/* foo.h */typedef struct Foo_ {    int    a;    double b;    int menuID;} Foo;Foo * createFoo(int a, double b);void destroyFoo(Foo *f);/* foo.c */#include "foo.h"#include "menu.h"#include "stdlib.h"#define FOO_MENU_NAME "Foo"static void foo(int a, double b);static int fooCallback(void *data);static void foo(int a, double b) {    /* ... */}static int fooCallback(void *data) {    Foo *f = data;    foo(f->a, f->b);    return 0;}Foo * createFoo(int a, double b) {    Foo *f = NULL;    f = malloc(sizeof *f);    if (!f) { return NULL; }    f->a      = a;    f->b      = b;    f->menuID = addMenuItem(FOO_MENU_NAME, fooCallback, f);    if (f->menuID < 0) {        free(f);        return NULL;    }    return f;}void destroyFoo(Foo *f) {    removeMenuItem(f->menuID);    free(f);}


[Edited by - Way Walker on November 7, 2009 5:13:06 PM]
Thanks guys!
I get the idea.

This topic is closed to new replies.

Advertisement