Jump to content
  • Advertisement

Archived

This topic is now archived and is closed to further replies.

Bob Jelly

Function pointers and C++ classes

This topic is 6534 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

Hi there ! I''m currently building a console system for my engine. I''m able to get a command line from the user, but the only problem is mapping the command to a function... I''m using classes for all parts of my engine. What I want to do is be able to do something like this in my engine initialisation : m_Console.AddCommand( "TheCommand", Class.Function ); Then the CConsole::ExecuteCommand( string strCommand ) would call the good function for each command. The problem is how can I use pointer to members functions in my classes ? I think that I could set these functions as static but is there any other way ? Thanks for the help !

Share this post


Link to post
Share on other sites
Advertisement
You could create a hash table for that purpose... If you wanna learn how to do that, just search for hash tables on the net...

you could also create a structure that contains the command string, and a pointer to the function... and maybe ask from the function to give you an index or something when it places the command string and the function in a table... you can easily call it later on... there are many ways to do that... just choose which one best suits you...

Share this post


Link to post
Share on other sites
I know that I will have to use a structure to hold the commands and the functions pointers. My problem is how to obtain pointer to classes functions that are not declared as static ? Is it possible ?

Share this post


Link to post
Share on other sites
quote:

What I want to do is be able to do something like this in my engine initialisation :

m_Console.AddCommand( "TheCommand", Class.Function );



Looks just like Visual Basic Script inside of Microsoft Excel.

It is possible.
You probably don't want this in a game engine, but if you are using MS VC++ pro edition, you can try adding a COM object into your project for each class object you have. From the Insert menu, click on Insert New ATL Object. Then follow the wizard that will generate code and add garbage to your project. Now you can edit the interface of that object using IDL (Interface Definition Language).

This will instantly makes your .EXE scriptable the way you are asking! (Nevermind the agonizing obscurity, the impenatrable overhead or the loss of flexibility of rewriting your program.)




Edited by - Marsupial Rodentia on June 27, 2000 2:49:43 PM

Edited by - Marsupial Rodentia on June 27, 2000 2:51:42 PM

Share this post


Link to post
Share on other sites
Try this:

        
typedef void (Class::*memberPtr)();

void CConsole::AddCommand( string strCommand, Class* obj,
memberPtr cmd )
{
// associate obj and cmd with strCommand

}

void CConsole::ExecuteCommand( string strCommand )
{
// use strCommand to retrieve obj and cmd


// now invoke the command

(obj->*cmd)();
}

m_Console.AddCommand( "TheCommand", &object, &Class::Function );


If the command doesn't need access to a particular instance of your class, then you're probably better off using static member functions. If you want separate classes to add their own commands, then static functions are almost surely the way to go. That way, AddCommand can just accept any C-style function pointer of the appropriate type.

For another example, take a look at OpenUT/Core/Inc/UnScript.h in the CVS repository for the OpenUT project. The Unreal engine uses pointers to non-static member functions to support native functions in UnrealScript.

A couple things to keep in mind if you do use the non-static approach:

1) Never try to treat a non-static member function pointer as a C-style function pointer, or vice-versa. Only static member functions work that way, since they don't have an implicit "this" argument.

2) Don't cast a non-static member function pointer to any other pointer type. A non-static member function pointer is a 32-bit value to Visual C++, but gcc uses a 64-bit representation. You may not plan to use gcc, but it's probably best to stay on the safe side and avoid any unnecessary assumptions.

Good luck with your project!

Edited by - EvilTwin on June 27, 2000 4:33:23 PM

Share this post


Link to post
Share on other sites
quote:
Original post by Bob Jelly

Hi there !

I''m currently building a console system for my engine. I''m able to get a command line from the user, but the only problem is mapping the command to a function...


EvilTwin already showed how you should probably use a typedef to define what the member functions to be stored. You can''t really go storing members of all different types of classes here, as that would really complicate things, so I''m assuming these member functions are all members of the same class.

But the way I would do it would be to use an STL Map class.

    
#include <map>

class MConsole
{
private:
typedef std::map<string, memberFuncPtr> StrFuncMap;

StrFuncMap CommandMap;

public:
void AddCommand(string cmdname, memberFuncPtr p)
{
CommandMap[cmdname] = p;
}

void ExecuteCommand(string cmdname)
{
StrFuncMap::iterator i = CommandMap.find(cmdname);
if (i != CommandMap.end())
{
funcPtr = (*i).second();
// Call the command on ''obj''

(obj->*funcPtr)();
}
else
{
// command not found

}
}
};


Some of that may not be 100% accurate since I''m doing this from memory. If you need to pass in class instances, you might need to store a "struct { class* instance, memberFuncPtr ptr }" instead of just the pointer. Either way, I just put ''obj'' in the above code, you need to work out how to get that to be the right instance, if applicable.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
I still don''t see why you can''t just pass the "this" pointer into the function implicitly.

typedef void (*CMDHANDLER)(Class* pThis)
void CConsole::Invoke (PTSTR pszCommand)
{
CMDHANDLER pfnCmdHandler = ...; // Get function pointer
pfnCmdHandler (m_pClassPtr); // Assume that the class pointer is a member of CConsole
}

void Class::HandlerA ()
{
// This handler executes
}


Share this post


Link to post
Share on other sites
quote:
you might need to store a "struct { class* instance, memberFuncPtr ptr }"


a STL pair would be better:

(using namespace std)


pair< Class*, MEMBERFUNCPTR > A(classInst, memberFunc);


that would make the command map defined as:


map< string, pair< Class*, MEMBERFUNCPTR > >


use some typedefs to clean it up, but you see what im getting at.

Share this post


Link to post
Share on other sites
Anonymous Poster -- You can do that, but you could only assign a static member function to pfnCmdHandler. If you want to end up calling a non-static member function, you''d need to do something like this:

    
static void Class::StaticHandler( Class* pThis )
{
if( pThis != NULL )
{
pThis->NonstaticHandler();
}
}

void Class::NonstaticHandler()
{
// Do the real work.

}

Share this post


Link to post
Share on other sites
EvilTwin:

"2) Don''t cast a non-static member function pointer to any other pointer type. A non-static member function pointer is a 32-bit value to Visual C++, but gcc uses a 64-bit representation. You may not plan to use gcc, but it''s probably best to stay on the safe side and avoid any unnecessary assumptions."

I agree, but I''m wondering why GCC uses 64 bits. All you need to call a procedure is 32 bits, after all. Couldn''t you use inline assembly language for compatibility? In reference to your previous remark, how do C COM interfaces work, then? When you call COM interfaces in C, you are forced to deal with explicitly calling them through their VTBLs and sending the THIS parameter in first.

Mansupial Rodentia:

There is really no need to use ATL or out-of-proc servers when working with COM. Smaller in-proc servers that use native COM interfaces are preferrable.



VK

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!