🔒 Locked
Varable Length functions, function pointers, and trouble!
Advertisement
Original Post
Hello, can someone please help me! Im trying to call a variable length function pointer from within a function that takes the function name, and the arguments from the function:
typedef void (__cdecl CBaseClass::*runfunc) (int, ...);
void runFunc(long time, CBaseClass *obj, runfunc func, int paramnum, ...)
{
va_list va_ArgumentList;
if(paramnum == 0)
return;
va_start(va_ArgumentList, paramnum);
(*obj.*func)(paramnum, va_ArgumentList);
va_end(va_ArgumentList);
}
The func im testing it upon has the following signature:
void __cdecl test(int n, va_list va_ArgumentList);
And the call is:
runFunc(1000, this, (runfunc)test, 3, 0.3, 0.6, 1.0);
Unfortunatly when it is called, the function "test" gets garbled arguments to it (in va_ArgumentList).
However, if I set up runFunc like this, it works:
void runFunc(long time, CBaseClass *obj, runfunc func, int paramnum, ...)
{
va_list va_ArgumentList;
if(paramnum == 0)
return;
va_start(va_ArgumentList, paramnum);
float fl_Red = (float)(va_arg(va_ArgumentList, double));
float fl_Green = (float)(va_arg(va_ArgumentList, double));
float fl_Blue = (float)(va_arg(va_ArgumentList, double));
va_end(va_ArgumentList);
(*obj.*func)(paramnum, fl_Red, fl_Green, fl_Blue);
}
Unfortunatly this is a bad solution, as in the final thing I will pass functions with varable lengths into runFunc. What do I do???
If you could help, thanks a lot for sparing the time and thought!
-wolfman
Well what I want to do is to pass lots of different functions to runFunc, each will have different numbers of arguments.
Thus the function pointer param in runFunc will have have "..." as a param, otherwise the function pointer will be of the wrong type to handle all of the functions, and thus the functions to be passed need this in order to be of the right type.
-wolfman
Thus the function pointer param in runFunc will have have "..." as a param, otherwise the function pointer will be of the wrong type to handle all of the functions, and thus the functions to be passed need this in order to be of the right type.
-wolfman
Your function pointer is declared like this:
but the function you assign is declared like this:
See the difference? One takes a variable number of arguments, the other takes 2 arguments. What does the body of your
Also, this just screams terrible design to me. I''d hate to come back to this after a few months and try to maintain it. There''s got to be a better way to do what you''re trying to do...
codeka.com - Just click it.
typedef void (__cdecl CBaseClass::*runfunc) (int, ...);but the function you assign is declared like this:
void __cdecl test(int n, va_list va_ArgumentList);See the difference? One takes a variable number of arguments, the other takes 2 arguments. What does the body of your
test function look like?Also, this just screams terrible design to me. I''d hate to come back to this after a few months and try to maintain it. There''s got to be a better way to do what you''re trying to do...
codeka.com - Just click it.
I tried test as void __cdecl test(int n, ...); and it gave me the same results.
I''ll try to explain what im doing, and yes, its probably the wrong way to do it, but I wanted to come up with my own design rather than use windows built in stuff.
Basicaly im trying to program my own demo, and what I want to do is to code up something that will enable me to set a time to call a function, and when the time is reached, that function is called. Then I want to pass lots of different functions to it so I can basicaly script my demo like so:
addTimedEvent(1000, this, (eventfunc)changeColour, 3, 1.0, 1.0, 0.0);
addTimedEvent(1000, this, (eventfunc)setSpeed, 1,500.0);
addTimedEvent(5000, this, (eventfunc)changeColour, 3, 0.0, 1.0, 0.0);
So I have a global event timer object that all my different demo classes can access, and add functions they have within them to the event timer. Is there a better way of doing this? I dont want to totaly hardcode the times into each seperate class, I want a centralised thing that controls it all. Ideas? Comments on my method?
Thanks,
-wolfman
I''ll try to explain what im doing, and yes, its probably the wrong way to do it, but I wanted to come up with my own design rather than use windows built in stuff.
Basicaly im trying to program my own demo, and what I want to do is to code up something that will enable me to set a time to call a function, and when the time is reached, that function is called. Then I want to pass lots of different functions to it so I can basicaly script my demo like so:
addTimedEvent(1000, this, (eventfunc)changeColour, 3, 1.0, 1.0, 0.0);
addTimedEvent(1000, this, (eventfunc)setSpeed, 1,500.0);
addTimedEvent(5000, this, (eventfunc)changeColour, 3, 0.0, 1.0, 0.0);
So I have a global event timer object that all my different demo classes can access, and add functions they have within them to the event timer. Is there a better way of doing this? I dont want to totaly hardcode the times into each seperate class, I want a centralised thing that controls it all. Ideas? Comments on my method?
Thanks,
-wolfman
i guess your''re programming solely in C
a C++ way to do it would involve functors (function objects) which can retain state information in the object and then be executed polymorphically with a call Execute().
i''m sure there''s plenty of info around about this
a C++ way to do it would involve functors (function objects) which can retain state information in the object and then be executed polymorphically with a call Execute().
i''m sure there''s plenty of info around about this
I''m unclear about what a __cdecl member function is. Where does the this pointer go?
Anyway, a va_list is not "...".
Your member functions need to take a va_list if you are wanting to pass them a va_list.
Anyway, you should use functors. The constructor of each object takes the parameter list, and the object has an operator()(void) method that does whatever action you want it to do.
Anyway, a va_list is not "...".
Your member functions need to take a va_list if you are wanting to pass them a va_list.
Anyway, you should use functors. The constructor of each object takes the parameter list, and the object has an operator()(void) method that does whatever action you want it to do.
Try making a base class, and some other classes whos constructors take that arguments you need, and the class it''s self does the task you want. Then pass the pointers of the base object and then write ''even->DoYourThing();'' (which should be a virtual function, by the way.)
Or something. . .
Or something. . .
How about you redesign things a bit differently.
Set up a global timer system. Then, in each object that you want to be based on a timer, have an "on_timer()" function. Register the class with the timer system to receive events at specific time intervals. The timer system will then call the class's on_timer() function at the specified time. How does that sound?
[edited by - fizban75 on June 14, 2002 12:33:10 PM]
Set up a global timer system. Then, in each object that you want to be based on a timer, have an "on_timer()" function. Register the class with the timer system to receive events at specific time intervals. The timer system will then call the class's on_timer() function at the specified time. How does that sound?
[edited by - fizban75 on June 14, 2002 12:33:10 PM]
Fizban, thats kinda what I want, but unfortunatly I want to call multiple functions in the same class. Thus I want the global system to call different functions in different classes multiple times, each with different parameters.
Thus I wanted to register a function with a global class, which was what my original post was trying to do.
DrPizza, the "__cdecl" is a compiler thing for VC++, that is needed to point to a function in a class. (If you dont include it, the compiler complains about the wrong pointer type).
I might have to end up with an ugly solution - calling a base class virtual function, which in a subclass is overidden, and then has a switch statement within it, so it does something like this:
As you can see, doing this for each class is not the best way, as a complex series of events would be a nightmare to change if I wanted to "try something new" in the timeline.
-wolfman
Thus I wanted to register a function with a global class, which was what my original post was trying to do.
DrPizza, the "__cdecl" is a compiler thing for VC++, that is needed to point to a function in a class. (If you dont include it, the compiler complains about the wrong pointer type).
I might have to end up with an ugly solution - calling a base class virtual function, which in a subclass is overidden, and then has a switch statement within it, so it does something like this:
void CClassDoesStuff::onTime(long time)
{
switch(time)
{
case(1000):
changeColour(1,0,1); break;
case(2000):
changeColour(1,0,0); moveTo(10,10,0); break;
case(4000):
scale(4); break;
default: break;
}
}
As you can see, doing this for each class is not the best way, as a complex series of events would be a nightmare to change if I wanted to "try something new" in the timeline.
-wolfman
quote:
Original post by Wolfman
the "__cdecl" is a compiler thing for VC++, that is needed to point to a function in a class.
Actually it''s calling convention specifier. __cdecl calling convention is required for variable-argument functions. You must match the calling conventions of function pointers and the functions they point to, but __cdecl isn''t needed to create a function pointer as such.
I was thinking you should do something like the following. Maybe someone else can add to it.
class SomeAction
{
public:
virtual ~SomeAction();
virtual void DoIt();
};
class SetColour: public SomeAction
{
public:
SetColour(float cr, float cg, float cb): r(cr), g(cg), b(cb)
{}
virtual void DoIt(void)
{
// do something regarding setting a colour
}
private:
float r, g, b;
};
class Move: public SomeAction
{
public:
Move(float px, float py, float pz): x(px), y(py), z(pz)
{}
virtual void DoIt(void)
{
// do something regarding moving
}
private:
float x, y, z;
};
void DoAnAction(SomeAction &action)
{
action.DoIt();
}
int main()
{
DoAnAction(SetColour(2, 3, 5));
DoAnAction(Move(0, 0, 10));
return 0;
}
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement