• Advertisement
Sign in to follow this  

Can I do this?

This topic is 3769 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Is it possible, in C++, to use a void pointer as a function pointer? In other words, given a void pointer, can I jump to that address in memory and continue execution? Obviously this would be extremely dangerous; I'm just wondering if it's possible.

Share this post


Link to post
Share on other sites
Advertisement
Oops, I didn't specify the problem completely. I should have added "without knowing the function signature at compile time".

Share this post


Link to post
Share on other sites
You must, of course, cast the pointer to the appropriate pointer-to-function type before calling it. Furthermore, you cannot do this with pointers-to-member-functions.

Share this post


Link to post
Share on other sites
Quote:
Original post by King of Men
can I jump to that address in memory and continue execution?


If you wanted to be clever(/evil) about it, and didn't mind getting your hands dirty with a little assembly, you could replace the stack pointer with the given address. There are a few registers that you'll need to update besides just the stack pointer, though (exactly which ones will vary, but the instruction pointer will need to be changed, for one).

Bruce Dawson discussed such a system for implementing micro-threads in Game Programming Gems 2 (read it here).

Share this post


Link to post
Share on other sites
Strictly speaking, you don't need to cast the pointer to the correct type. You can cast it to whatever you feel like and call away. Chances are your app will crash very soon after that call and you'll be left looking at some disassembly trying to work out what the correct signature is. Hey, if all else fails you could (in x86) just do something like


void* p_myfuncptr;
__asm
{
call [p_myfuncptr]
}



Good luck with that! ;-)

Share this post


Link to post
Share on other sites
Quote:
Original post by King of Men
Oops, I didn't specify the problem completely. I should have added "without knowing the function signature at compile time".


Do you know the "set of possible signatures" at compile time? And can you figure out the one to use at run-time prior to invocation?

The ability to generically invoke nearly any function dynamically is done all the time in frameworks / libraries. But just like and factory / serialization or downcasting interface scenerio ... something has to exist to manage the decisions and some data must be provided to drive the choice of which to use.

For instance you can have an abstract class like InvokableMethodType that you derive from for each signature you want to support. Each derived class can register their existence with the base class, preferably including information like an ID / GUID and some friendlier name. Then something like your game scripting language could do:

Invoke(FunctionVoidIntInt,PlotPixel,1.0,2.0)

which your engine could process as ... A) look up the invocation class "FunctionVoidIntInt" in the type / signature manager. Then lookup up the method address for PlotPixel stored probably in another manager. Then invoke it with the 2 arguments given (after casting to type).

Of course this system can be as simply or complex as needed.

Share this post


Link to post
Share on other sites
Quote:
Original post by Xai
Quote:
Original post by King of Men
Oops, I didn't specify the problem completely. I should have added "without knowing the function signature at compile time".


Do you know the "set of possible signatures" at compile time? And can you figure out the one to use at run-time prior to invocation?


Well, yes, but I was kind of hoping to not have to do a lot of management work... Oh well. Casting it is, then. Although dropping into assembly would be nice if I thought I could make it work.

Share this post


Link to post
Share on other sites
Dropping to assembly would not solve the problem of having to know the types and signatures involved, really. In fact (having done it) it's probably going to result in more management.

Share this post


Link to post
Share on other sites
Ok. Still hoping for ways to save myself typing. I am trying to make a template class which takes some class T, and a function pointer returning T and taking a char* as argument; like so:


template <class T, T (*initFunction) (char*) > struct FunctorWithInitialiser {
FunctorWithInitialiser<class T, T (*initFunction) (char*) (char* str) {
value = new T((*initFunction)(str));
}
private:
T* value;
};


Unfortunately gcc tells me I have a syntax error before the * token, which apparently refers to the 'char*'. If I remove the char so the code reads I get a different error.


template <class T, T (*initFunction) () > struct FunctorWithInitialiser {
FunctorWithInitialiser<class T, T (*initFunction) (char*) () {
value = new T((*initFunction)());
}
private:
T* value;
};


I get this error instead:

FunctorWithInitialiser<T, (T)((*in))()> () specified as declarator-id
warning: no return statement in function returning non-void

So it looks as though it thinks I'm declaring a member function instead of a constructor. Is there some special syntax for template constructors that I'm not aware of? And what is the objection to the char*? I tried putting a 'typename' in front, but then I get a syntax error before 'char'. These be deep waters, matey...

Share this post


Link to post
Share on other sites
Assuming for a moment that the second template argument is a pointer with external linkage...

template <class T, T (*initFunction) (char*)> 
struct FunctorWithInitialiser {
FunctorWithInitialiser(char* str) : value(new T(initFunction(str))) {}
~FunctorWithInitialiser() { delete value; }
private:
// Disable CC and operator= here
T* value;
};
?

Share this post


Link to post
Share on other sites
Ah, ok, I see now - you don't put the template arguments in the constructor signature. Fair enough. This code now compiles:


template <class T, T (*in) () > struct FunctorWithInitialiser {
explicit FunctorWithInitialiser () {
value = new T((*in)());
}

private:
T* value;
};


And that also removes the trouble with the char*, for some reason. Thank you, GameDev; sorry for taking up your bandwidth. I may return if I run into run-time problems, or trouble with actually instantiating the template. :)

Edit: Wow, ToohrVyk, ninja speed! Ratings for you. :)

Share this post


Link to post
Share on other sites
So, here's what I ended up with, which I'm rather pleased with because it uses template and preprocessor magic, two subjects I didn't know very much about before. I still know very little, but more than I did two days ago. :)

What I want is a lookup from string to function. I make a Functor class to encapsulate the function, and a map gTable from string to a function returning a Functor. Then I make a class like this:

template <class T> struct MakeFunctor : public Functor {
virtual void* eval ();
static T* create () {return new T();}
};


and can now define new Functor classes with automagically generated create and eval functions just so:

struct SomeFunctor : public MakeFunctor<SomeFunctor> {};


That still leaves the problem of initialising my lookup table of Functor creators. My first solution was to just have an initialisation function, and manually code in all the various types of functor, with a corresponding key. But that means I have to change things in two places to add a new Functor, which is tedious. So I created a class to do things for me at static-init time:


template <class T> struct LookUpper {
LookUpper (const char* key) {gTable[std::string(key)] = (Functor* (*) ()) &T::create;}
};

#define FUNCTOR_DEF(name, key, uniq) struct name : public MakeFunctor< name > {}; LookUpper< name > _p__UNIQUE_ID ## uniq ( #key )

FUNCTOR_DEF(AddFunctor, +, 1);
// (...)

#undef FUNCTOR_DEF


My definition of a Functor now declares the 'create' and 'eval' functions, provides a definition of 'create', and correctly initialises the lookup table at start-time. All I have to do is provide the definition of the 'eval' function, and if I didn't want to do this minimal amount of programming I shouldn't have made a functor in the first place! I think this is truly minimal boilerplate, and I'm rather happy with it, although I sat up until 0200 last night trying to figure out the compiler messages. Also, trying to do static inits in header files is a bad idea. :) But it works now! Yay!

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement