Archived

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

BS-er

Calling C++ member functions through pointers

Recommended Posts

What I would like to do is make a template class that can be set up to call some basic set/get member functions of the input class type. This would be for setting and getting properties. For example a class has a bunch of set and get functions for floats, ints, vectors, quaternions and other common types. What I want this template class to do is assist in setting and getting member values via a text string argument. So if my template class is called "PropertyInterface", instantiation of my template would be something like:
            
PropertyInterface<CMyClass> TheClassInterface;
     
And this interface class can be configured after instantiation as follows:
                       
TheClassInterface.RegisterFloatInterface("MaxSpeed", CMyClass::GetMaxSpeed, CMyClass::SetMaxSpeed);
  
given the function prototypes:
  
float CMyClass::GetMaxSpeed();
void CMyClass::SetmaxSpeed(Float);
  
Maybe instead of RegisterFloatInterface, a general function could be overloaded such that you need not specify "Float" in the function name. So through this interface class you would set and get values using text names, maybe like the following:
                     
TheClassInterface.SetCurrentInstance(&m_MyClassInstance);
TheClassInterface.Set("MaxSpeed", 30.0f);
    
Basically I'm asking for some tips on handling pointers to member functions to make something like this work in a template class. Specifically, how do you define their types, and how do you call them?. It may even need to deal with inheritance, i.e. set and get functions of the ancestor classes of CMyClass. Value of good ideas: 10 cents per dozen. Implementation of the good ideas: Priceless. Proxima Rebellion - A 3D action sim with a hint of strategy [edited by - BS-er on March 2, 2003 11:27:37 AM]

Share this post


Link to post
Share on other sites
If you want to use a string to tell it what property to set, then you need to use a soft-architecture and store the values in an associative container (like a map).

Then you just need to add a get & set method to access data in the container.

Share this post


Link to post
Share on other sites
Thanks for your reply, but I''m not sure I''m any closer. I want to be able to take any existing class that has these set and get functions for certain data types, and create one interface class instance that can initialize one or all of them (by passing it pointers to the class instances). There would be no modifying the existing class.

I would use an associative container, but it would be to access the function pointer. I think I have the general approach decided, but I never seem to find good documentation on pointers to C++ member functions, and how to type, declare and use them.

Value of good ideas: 10 cents per dozen.
Implementation of the good ideas: Priceless.

Proxima Rebellion - A 3D action sim with a hint of strategy

Share this post


Link to post
Share on other sites
If you want to use a string to tell it what property to set, then you need to use a soft-architecture and store the values in an associative container (like a map).

Then you just need to add a get & set method to access data in the container.

Share this post


Link to post
Share on other sites
quote:
Original post by Magmai Kai Holmlor
[...] you need to use a soft-architecture [...]

Soft-architecture? Have you just made that up? The only meaning I can find for it would not make sense in the used context.
quote:

[...] store the values in an associative container (like a map).

Consider the following function signatures...

  
void CMyClass::SetSomeValue(float);
void CMyClass::SetSomeOtherValue(int);
float CMyClass::GetSomeValue() const;
int CMyClass::GetSomeOtherValue() const;

How do you propose to store pointers to those types in a single map? How would you package the function arguments and return values in a manner that avoids loss of information or of type-safety?
quote:

Then you just need to add a get & set method to access data in the container.

That wouldn''t solve what he''s trying to do, which isn''t possible without either escaping C++''s type-system and then writing (or otherwise obtaining) the code to implement a dynamic type-system, or creating a ridiculously convoluted template solution that would do well as the subject of a Ph.D. paper. There might be a more C++ like way of doing what BS-er wants, but that depends on what problem he''s actually trying to solve, which isn''t apparent.

Share this post


Link to post
Share on other sites
I'm doing this right now.
Compiletime it's just a matter of template meta-programming, so that the overhead is nil - same as an straight assign / function call.
In Runtime, it's more interesting. You can use templates that take any times for any number of arguments up to a predefined level, then, when it is instantiated, check the type ID of that type to the type ID exposed in the property definition...
Yep.
That's what'll I do (I've been stuck on this since sunday)
..
This is what my code looks like right now (Compiletime only):

    
struct vertex_b {
float pos[3];
void rotate(float);
};

namespace VertexProp {
GDN_DEFINE_PROPERTY(x)
GDN_DEFINE_PROPERTY(y)
GDN_DEFINE_PROPERTY(z)
GDN_DEFINE_PROPERTY(Rotate)
}

template <> struct MetaClass<vertex_b> {
typedef Implements<
VertexProp::x, MemberArray<vertex_b,float,&vertex_b::pos,0>,
VertexProp::y, MemberArray<vertex_b,float,&vertex_b::pos,1>,
VertexProp::z, MemberArray<vertex_b,float,&vertex_b::pos,2>,
VertexProp::Rotate,Function1<void,vertex_b,float,&vertex_b::rotate>
> Implemented;
};

typedef Interface<
VertexProp::x,float,
VertexProp::y,float,
VertexProp::z,float,
VertexProp::Rotate,Function<void,float>
> VertexIntf;

vertex_b obj;
BindToClass<VertexIntf,vertex_b> vertex(obj);
cout << "("<< vertex.x.Get() << "," << vertex.y.Get() << "," << vertex.z.Get() << ")";
vertex.rotate(12);
//..and to come

BindToClassRT<VertexIntf,vertex_b> vertexRT(obj);
vertexRT["x"] = 12.23;
vertexRT["y"] = 23.45;
vertexRT["Rotate"](123.45);


There are more stuff, like member get/set pairs, read only properties; the function system works polymorphically.
Properties can have different get / set type signitures. And so on. There is a list, I haven't got around to finishing the features list yet

(I hear the flames already....)
*500

EDIT: And, you can do proper Interface MI (java style MI) with the Property::Inherits property

-----------------------------
Gamedev for learning.
libGDN for putting it all together.

[edited by - risingdragon3 on March 3, 2003 4:52:48 PM]

Share this post


Link to post
Share on other sites
this question triggers my interest - i am wondering something similar.

I''m looking at SDL wondering if it would be possible for me to add multithreading functionality.


  
class clientController{
private:
int updateThread(void *unused){
//blah

}

SDL_Thread *thread;
public:
clientController(CConnection *con, linklist *others ){
//blah

thread = SDL_CreateThread(updateThread, NULL);
}
//blah

}

--------------------Configuration: Server - Win32 Release--------------------
Compiling...
mainbrum.cpp
C:\programming\0-JETTHUNDER\ChatServer\clientController.h(64) : error C2664: ''SDL_CreateThread'' : cannot convert parameter 1 from ''int (void *)'' to ''int (__cdecl *)(void *)''
None of the functions with this name in scope match the target type


sadly this doesnt work. If it did, the creator would create a thread and it would run happily along. anybody know how to make it work???

Share this post


Link to post
Share on other sites
I've thought about this one as well, After about a week, i came up with a lot of template and inherited classes and it really wasnt as good as what i wanted so i through it out. It's pretty dirty, especially trying to get it to be scalable for more than just getters and setters, or a predefined number and type of argument and written in such a way that modification to the existing frame work to support methods with different types and number of parameters would be minimiazed. If anybody has a good solution, please post. I think Corba has a implementation respository where classes can register their methods through interfaces and others can look up into this repository for to access methods (not sure as i have never used this feature of Corba)

[edited by - _walrus on March 3, 2003 5:09:27 PM]

Share this post


Link to post
Share on other sites
Sounds a bit like a remote procedure call to me. Don''t know if you need the templates however.....

To set up pointers to member functions you can do something like...

class base; // Forward Dec

typedef float (base::*GFPTR)(void); // Pointer to a member function returning float, no parameters
typedef void (base::*SFPTR)(float); // Pointer to a member function returning void, taking float

The class base can then provide the registration for the methods

void base::Register( const char* _name, SFPTR _set, GFPTR _get )
{
// Save in some database here
}

You can then derive from the class base to provide the set/get methods you need

class derived : public base
{
public:
float GetSpeed( ) const;
void SetSpeed( float );
};

Then you can register with something like

void derived::RegisterInterfaces( void )
{
base::Register("Speed", &GetSpeed, &SetSpeed);
}

Ciao

Share this post


Link to post
Share on other sites
_walrus: check out libGDN when I finish this part of it. It''s scaleable: getter / setters, members as indices in an array, members as members, read only properties : getters only;
functions with any number of arguments and any return type;
and so on.
Inheritable properties.
No need to have a central Register() funnction.
No overhead (in compile time).
(this means you can use this in your tightest game loop).
There is no storage of a std::map.
The defintino of the properties is a little verbose, though. But it''s powerful.
Polymorphism works correctly.
Getter and setters can have different return types.
You can even have write-only properties.

The impelmentatino is 1000 lines+ tho. It works on (supposedly) MSVC6, I don''t have access to it, but I didn''t use PTS at all, so it should be fine.

SirHando:
But you can do better =P. Come on!


-----------------------------
Gamedev for learning.
libGDN for putting it all together.

Share this post


Link to post
Share on other sites
This is a very interesting problem, but I fail to see the usefulness of this approach over simple polymorphism. Without further speculation, can someone point advantages to this approach over whatever alternatives there is (I''m thinking hardcoded function calls).

Personally, I don''t very much like templates, they''re ugly - but I will use them iff the need arises, which it sometimes does

Share this post


Link to post
Share on other sites
Serialization. (A Big Thing).
Reflection into a scripting language.
Manipulating classes generically in things like scene graphs, especially if you are writing library code.
Knowing about yourself (what type are we? what are each of the member''s names, and what are the types of each member? functions?)



-----------------------------
Gamedev for learning.
libGDN for putting it all together.

Share this post


Link to post
Share on other sites
It''s certainly not finished. And I didn''t even tell you where to get it
I feel bad!
It''s in the sandbox..in the CVS. You can view it on the sourceforge page (go to Web CVS) and go to the sandbox.
I''m going to upload the newest version now ... (But the Runtime stuff ain''t finished yet *getting there*)
*500

-----------------------------
Gamedev for learning.
libGDN for putting it all together.

Share this post


Link to post
Share on other sites
The C++ Faq Lite has an excellent page on this topic that REALLY helped me when I ran into this the other day.

http://www.parashift.com/c++-faq-lite/pointers-to-members.html

Share this post


Link to post
Share on other sites
quote:
Original post by risingdragon3
It''s certainly not finished. And I didn''t even tell you where to get it
I feel bad!
It''s in the sandbox..in the CVS. You can view it on the sourceforge page (go to Web CVS) and go to the sandbox.
I''m going to upload the newest version now ... (But the Runtime stuff ain''t finished yet *getting there*)
*500

-----------------------------
Gamedev for learning.
libGDN for putting it all together.


I yeah i couldn''t find it when i visited the site, but i''ll check back early next week, thanks.

Share this post


Link to post
Share on other sites