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;
}
Member function pointer calling [WORKING]
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:
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]
Already invented.
Sample usage:
Sample usage:
struct Foo{ void Bar();};Foo object;boost::function<void()> function = boost::bind(&Foo::Bar(), &object);/*...*/function(); // calls object.Bar();
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:
(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.
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.
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);
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.
edit:
this is what I got so far.
//worksunsigned long long functptr = (unsigned long long)&main;//gives error (renamed do to doit)unsigned long long functptr = (unsigned long long)&A::doit;
That's because member function pointers work differently. See this link for an in-depth dissection of the implementation details of member function pointers.
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.
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.
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.
#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.
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:
All in all, it looks like a very fragile hack.
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.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement