Skip to main content
GameDev.net gamedev.net
🔒 Locked

Generic functor storage?

Started by CJM Jan 18, 2005 at 7:45 PM 4 replies 700+ views
Original Post
CJM
CJM
Heya, I'm currently working on some stuff for my engine which retrieves and stores functors for use in a scripting system. I'm coding in MSVC 7. Now, I know that different functors [read member functors] can have different sizes (either 4 or 8 bytes usually). Is there any way to store and retrieve pointers to member functions or pointers to global functions and not their parameters for use in assembly 'call' statements? Currently, I've got to have a big switch which calls the right function [an __asm{ call Foo::Bar }], but I'd like something a little bit easier to change. I've handled all of the parameters and return stuffs, and just need to actually store these call function pointers somewhere. So... is there a way to, for example make this code work [ie compile]...

#include <windows.h>

class Foo
{
public:
	char Bar();
};

char Foo::Bar()
{
	return '0';
}

class Class
{
public:
	int Func();
};

int Class::Func()
{
	return 211;
}


int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
	//need to be able to store address of Foo::Bar or Class::Func (and not parameters) in a variable
	int(*funcPtr)(void)=0;
	switch (0)
	{
	case 0:
		funcPtr=reinterpret_cast<int(*)(void)>(&Foo::Bar);
		break;
	default:
		funcPtr=reinterpret_cast<int(*)(void)>(&Class::Func);
		break;
	}

	return 0;
}


Kudos, CJM
CJM
CJM
Results:

Turns out that my original method works quite well, though I thought it was broken because it was returning memory addresses which were not the ones MSVC thought it pertinent to give me, hmmm, the C++ stuff must give pointers not including the prologue code.

For those who are interested, or if you're wanting to help me find a better way, I just copy the memory to eax and then back to an int, a dodge hack, but hey...

<template T>int FuncToInt(T funcPtr){  int temp;  __asm{ mov eax, funcPtr };  __asm{ mov temp, eax };  return temp;}


Hope this helps someone if they come up against the same problem...
Anyone got any ideas for how I can do this smarter?

CJM
Zahlman
Zahlman
What you're doing would require 'static', i.e. class member functions (as opposed to object member functions) to work properly. Otherwise you're looking at "bound member function pointers"; you need to specify an instance of the class upon which the member function will be invoked (through the pointer) when the pointer is dereferenced.

Anyway, that's not really what functors are; you should instead be thinking along the lines of classes that override operator(). Then you would store instances of appropriate classes. Be warned: trying to do dynamic typing is working against the grain of the C++ language. You'll find things a lot easier if all those operator() overloads take the same input arguments and return the same thing. If you're interfacing to a scripting language, you might make a common class that represents objects in the scripting language: then the setup might look like this:

class FooScript : public Script {  ScriptObject& operator() (const std::vector<const ScriptObject>& args);}ScriptObject& FooScript::operator() (const std::vector<const ScriptObject>& args) {  // Read a specific file, interpreting its contents as a function in your  // scripting language, and passing it the args. Return the result object.}// Later on in the "script manager":scriptsToExecute.push_back(FooScript());


You may want to look at how, for example, the Python<->C API is implemented. You might also have better luck asking in Scripting Languages and Game Mods.
ajas95
ajas95
Quote:
Original post by Anonymous Poster
The size of a method pointer is not guaranteed to be 32-bits; even in MSVC where it can vary depending upon situation.

http://www.codeproject.com/cpp/FastDelegate.asp


I use FastDelegate all the time now. That library rocks. OP is strongly encouraged to at least read the article, as it deals exactly with what he is trying to accomplish.
CJM
CJM
Heya,

Thanks everyone who posted responses. I'm currently going over the article, and delegates are exactly what I was looking for I think. Basically put, I'm implementing a scripting system from which I can invoke any existing C++ function in my application at runtime, [for my debug game console, not release] because I didn't want to have to write code to access everything, and the method that I was using was quick and dirty, but worked [on all of the functions I'd put in and tested so far].

I have pretty strong constraints on the types of functions that I can call, I don't use very much inheritence in the engine, and I store the 'this' pointers seperately and load them up properly [so that I can invoke on any object]. In addition to the code that I posted in my second post, I'll also check that the pointer's size is <=4, or not store it and log a message [just so nothing bad happens]. But yeah, I'll look into delegates, they look just like what I'm wanting to do.

Thanks.

CJM

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.