Home » Community » Forums » General Programming » function pointers and functions with various arguments (C)
  Intel sponsors gamedev.net search:   
[Control Panel] [Register] [Bookmarks] [Who's Online] [Active Topics] [Stats] [FAQ] [Search]

Add Forum to Favorites |  Send Topic To a Friend | View Forum FAQ | Track this topic


 Last Thread Next Thread 
 function pointers and functions with various arguments (C)
Post New Topic  Post Reply 
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(); //?

________________________
My first (and probably last) demo

 User Rating: 1117   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

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

Atheron MMORPG

 User Rating: 996   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

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.

 User Rating: 1566   |  Rate This User  Send Private MessageView ProfileView JournalView GD Showcase Entries Report this Post to a Moderator | Link

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!

________________________
My first (and probably last) demo

 User Rating: 1117   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link


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/


 User Rating: 1018   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

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.

________________________
My first (and probably last) demo

 User Rating: 1117   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link


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.

 User Rating: 1018   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

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]

 User Rating: 1413   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Thanks guys!
I get the idea.

________________________
My first (and probably last) demo

 User Rating: 1117   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

All times are ET (US)

Post Reply
 Last Thread Next Thread 
Forum Rules:
You may not post new threads
You may post replies
You may not edit your posts
You may not use HTML in your posts
Jump To:
Administrative Options: