Jump to content
  • Advertisement
Sign in to follow this  
Tjaalie

Member function pointer calling [WORKING]

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

Dear Thread reader, I had an idea about a class that will allow me to call member functions like they where normal functions. I'm not at my development pc right now so I can't really test this but I tough that maybe one of you guys knows if this might work. Here is a sample:
typedef int (*memfunct)(void* _this, int argument);

class member_function
{
public:
  member_function(void* _class, memfunct funct)
  {
    m_class = _class;
    m_funct = funct;
  }

  int call(int argument)
  {
    return m_funct(m_class, argument);
  }

private:
  void*    m_class;
  memfunct m_funct;
};

class A
{
public:
  int do(int argument)
  {
    std::cout << argument;
    return argument+1;
  }
}

int main()
{
  A aclass;
  member_function afunction(&aclass, (memfunct)A::do);
  
  afunction.call(15);

  return 0;
}


Now my question is, will this work or do I have to do some secret assembly magic? I have a general idea of how that will work. Just pop all arguments (including the this pointer) and then call the function address. But of course it would be nicer if this worked. I will check it out as soon as I get to my dev pc. Ow and I'm using linux so I would compile this with g++. Tjaalie, [Edited by - Tjaalie on August 19, 2009 8:55:02 AM]

Share this post


Link to post
Share on other sites
Advertisement
No that won't work. If it does for testing, then it's just a lucky coincidence.

You can, however, still do that - safely and effectively - via boost::function and boost::bind:

A aclass;
boost::function<int(int)> afunction = boost::bind(&A::foo, boost::ref(A));

afunction(16);

(btw you can't call your function do, that's a keyword)

Edit: Ninja'd. BTW Sc4Freak when you bind, get rid of the () or it looks like you're trying to call the function.

Share this post


Link to post
Share on other sites
Quote:
Original post by nullsquared
Edit: Ninja'd. BTW Sc4Freak when you bind, get rid of the () or it looks like you're trying to call the function.

Ah, yes. Nicely caught. [grin]

Corrected:
boost::function<void()> function = boost::bind(&Foo::Bar, &object);

Share this post


Link to post
Share on other sites
Thank you, I know of the template stuff but I tough it looked nice if that would work. Too bad, I actually found a compiler on this computer and tried some stuff. I was able to get the address of a normal function into a 64 bit integer, but I couldn't get a member functions address. Is this also impossible? I'm just messing around with some idea's it doesn't really have a function yet, but it will as soon as my scripting engine will be capable of calling c++ functions. I rather not use boost because I'm programming for my own fun and want to do everything from scratch, its really fun to reinvent the wheel from a experience point of view. But thanks for your quick responses, that's why I love these forums. So is it possible to get the address of the function into a integer (or void*) I know this is really bad practice.

edit:

this is what I got so far.


//works
unsigned long long functptr = (unsigned long long)&main;

//gives error (renamed do to doit)
unsigned long long functptr = (unsigned long long)&A::doit;

Share this post


Link to post
Share on other sites
That's because member function pointers work differently. See this link for an in-depth dissection of the implementation details of member function pointers.

Share this post


Link to post
Share on other sites
Quote:
Original post by Tjaalie
it will as soon as my scripting engine will be capable of calling c++ functions.


That's precisely why you want to use boost. Luabind, which is a C++ bindings library for Lua, makes extensive use of boost. This allows you to mix and match C/C++ functions/member-functions/functors and Lua functions very, very easily.

Share this post


Link to post
Share on other sites
Call me crazy but I got it to work. Here is the totally messy code that shouldn't be used for anything other than experiments like this. I'm not going to use this code because this is probably undefined behaviour that somehow works the way I want it to work.


#include <iostream>

typedef int (*memfunct)(void* _this, int argument);

class member_function
{
public:
member_function(void* _class, void** funct)
{
m_class = _class;
m_funct = (memfunct)*funct;
}

int call(int argument)
{
return m_funct(m_class, argument);
}

private:
void* m_class;
memfunct m_funct;
};

class A
{
public:
int doit(int argument)
{
std::cout << argument;
return argument+1;
}
};

int main()
{
A aclass;
int (A::*funct)(int) = &A::doit;
member_function afunction(&aclass, (void**)&funct);

afunction.call(15);

return 0;
}




It prints '15' when compiled using g++. Maybe someone dares to try this with visual studio, just to see if it works.

edit:
I tried the code with member variables in the class A. Everything seems to work just as expected. If I can find a way to cleanly convert the member function to a void** without the need of the extra variable I might be able to actually use this. Although maybe not the smartest thing to do but it seems to work.

Share this post


Link to post
Share on other sites
With VC 2005 your code outputs 1245027. It seems that you are making some unsafe assumptions about how a member function call happens.

It outputs 15 if you explicitly specify __stdcall as calling convention:


class A
{
public:
int __stdcall doit(int argument)
{
std::cout << argument;
return argument+1;
}
};

int main()
{
A aclass;
int (__stdcall A::*funct)(int) = &A::doit;
member_function afunction(&aclass, (void**)&funct);

afunction.call(15);

return 0;
}



All in all, it looks like a very fragile hack.

Share this post


Link to post
Share on other sites
haha, funny.
I don't think I will be using this. The only way to make this work in a way that I think has some nice notation is with a marco from hell.

Share this post


Link to post
Share on other sites

This topic is 3258 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.

Guest
This topic is now closed to further replies.
Sign in to follow this  

  • Advertisement
×

Important Information

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

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!