function pointers... [SOLVED]

Started by
20 comments, last by the_moo 17 years, 11 months ago
hey all, i'm now trying to create a queue sort of system for actions that an object in my engine can use. basically it should take a function pointer and a list of the variables that should be passed when the function is called. i've had another method half working but it was using a bunch of pre-defined variables in a single struct (so like 3 floats and a string, etc.) and a constant value that was used to determine the function that was used to add the action to the list... anyway it was very confusing, very inefficient (for me to code) and a huge hassle to use. so now i've looked into function pointers... the problem i have is the fact that they are so rigid; everything has to be exact and that is making things difficult for the situation. so my question is this: is there any way (like tricks, library, etc.) that i can create a function pointer that can point to any function no matter what the return and/or the parameters? as far as i'm aware no such thing can be done but i wanted to see if anyone else could advise me otherwise or give some advice. thanks! [Edited by - the_moo on May 14, 2006 10:02:22 AM]
the_moo
Advertisement
If you don't know exactly which function you're calling, then you really wouldn't know what type of data to pass into it, right?

The method of queueing up function and parameter/return value heap pointers should most definitely work. What problem are you running into here?

I have constructed something like this to iteratively execute user-defined expressions, using a math library's functions to perform the operations. Did you want to look at the source?

Maybe you need to look at your situation a little differently, with the end solution in mind. Or describe it here in further detail for others to analyze.

Cowpower!
boost::function, although its still going to require a static (i.e., compile-time) function signature. The boost::bind library will let you create "closures" of sorts to transport one function type to another. It's not going to be exactly what you want, however.

The typed nature of C++ makes what you want to do particularly difficult. It can be done but you'll be doing quite a bit of legwork and potentially some very un-typesafe hacks. Generally, its not a good idea and it isn't even required -- you just think you want it. It's a much cleaner design to simply fix the signature of the callbacks passed into your library.

The reason "runtime-typed" function pointers are basically useless in this situation is its not exactly clear what your library is supposed to do with the function. Let's say you do manage to implement a function pointer construct that does what you want. Your library then takes an instance of this super-function-pointer and stores it, to invoke later as a callback. What parameters will your library pass to the function? It has no idea what to pass and consequently can't pass anything meaningful. If it DOES know what to pass than chances are your library is too tightly coupled with the client code, or the library could have just made the function signature static since it knew exactly what information it was going to pass.
I'm not an expert, but i have two ideas for this:

1) use functions like this one:
void* func(void*);
this is unsafe, but if you code it carefuly - you'll have lots of typecasts, and everything will work.

2) use functor objects, all implementing this interface:
class FunctorBase {
public: virtual void Execute () = 0;
};
Now, parameters can be passed to constructors of those functors. Or some set/get methods to set params/get result.

Maybe someone else has more ideas?
I was thinking about function objects too. You won't be able to execute the function "regardless of the return type", as you mention somewhere, but that's impossible anyway. You can't call a function and not know what it will return, unless you also want to use variants for this.
ok i've now got everything working but the assigning of the function pointers through a function parameter. i was just reading all the restrictions of member function pointers and am guessing that i won't be able to do what i want now...
see, the function to "queue" an action is a member function of my object class (and so is the queue list variable for all actions). i want to be able to assign any function pointer when queuing(??) from any classes that i may come up with outside of my engine.

now i know that this isn't sounding good so if it can't at all be done that's fine, but then i'm back to the same spot as before...

thanks again,
the_moo
Once again, this is something that boost::function and boost::bind can help you with.
If you're in C++, use objects instead.
If you're in C, you'll have to cast from void*
One solution would be to return a bool or int for a success code, passing in a single const reference to an object of type Uberclass.

This class would contain all of the variables available system-wide, providing massive function abstraction for a reasonable cost in memory -- 2GB RAM is common these days!

It is very handy for writing plug-in shaders in C++.

I doubt you're writing a math class, but
#include <string>using std::string;#include <iostream>using std::cout;using std::endl;class Uberclass{public:	int ia, ib, ic, id;	float fa, fb, fc, fd;	size_t la, lb, lc, ld;	string sa, sb, sc, sd;	int iadd(void)	{		return (ic = ia + ib);	}};int main(void){	Uberclass u;	u.ia = 4;	u.ib = 2;	int answer = u.iadd();		cout << answer << endl;	cout << u.ic << endl;	return 0;}


[Edited by - taby on May 1, 2006 9:36:48 PM]
A possible way around it (only really feasible assuming your using standard datatypes, like unsigned int, float etc...) is through the use of unions.

union UberReturn{	float		fdata;	unsigned int	uintdata;	char		cdata;};UberReturn uberFunction ( void* whatever ){	UberReturn val;	val.fdata = 0.0f;	return val;}typedef UberReturn (*uberFunctionPointerType) ( void* whatever );


If you need to implicitly know what its returning, then the union can be wrapped in a struct along with an enumeration too.

This topic is closed to new replies.

Advertisement