Sign in to follow this  
szecs

function pointers and functions with various arguments (C)

Recommended Posts

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(); //?

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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!

Share this post


Link to post
Share on other sites

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/

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

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[i])
{
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.

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this