C++ runtime member function access by string name - c++

I have two classes:
class MyClassInfo {
public:
void AddMethod(std::string name, void* pointer); // I don't know what signature should be
}
class MyClass
{
public:
void SetField1(int f1);
int GetFileld1();
private:
int field1;
};
I need to be able to access the methods of MyClass by name (string) during runtime. I don't want to use any libraries (except boost) and/or compiler functionality (such as rtti) to do that.
I don't know which signature I should use in AddMethod method, because I don't know how to transmit the function pointer to the function. This function must be a universal function which allows to add any method. Maybe you know a better variant how to do that without MyClassInfo. Any help will be appreciated.

That is not possible in directly C++. You will have to look at alternatives like creating a map of names to member function pointers. But even that would require consistent method signatures.
Something like
std::map<std::string, int (MyClass::*)(void*))
for instance. Your AddMethod signature would then look like this
void AddMethod(std::string name, int (MyClass::* pointer)(void*));
and you would call it like this
info.AddMethod("someMethod", &MyClass::someMethod);

If all functions you want to pass through AddMethod have the same signature (possibly after binding some of the arguments), you can use this signature:
void AddMethod(std::string name, boost::function<int ()> func);
and use like this:
info.AddMethod("GetFileId1", std::bind1st(std::mem_fun(&MyClass::GetFileId1), &MyClassInstance);
If the functions have different signatures, you could store them using boost::function_base:
void AddMethod(std::string name, boost::function_base func);
and you use it like above. The challenge is now to find out exactly what type is stored in the boost::function object so you can use it.

Related

Can I Create a Higher Order Function With Funciton Parameters from Different Classes?

So, I have this project where I have to recreate the most basic of MySQL functions, operating over a database of Songs (which are represented in a class).
I have created another class which is my Interface (user interface). I use it for getting commands, recognizing parameters, and so on. I want to create a higher order function, which takes several parameters. Some of them will be primitive data types, but there will also be two functions as parameters.
Now, one of the functions comes from the same class (Interface), but the other function comes from the Songs class. The problem is that I can't figure out how to reference the function within that class?
I was thinking of making the class static because you can only create one database of type Songs anyways. That would most probably give me the possibility of using the Songs:: reference, but I'm not sure that this is going to fix my problem.
Besides a solution, I am also asking for a more detail explanation on higher order functions in C++, I can't seem to find a good resource. And all of the resources that I've found don't say anything about higher order functions that take parameters of functions from other classes.
class Song
{
public:
string getName() const;
string getSinger() const;
unsigned int getLength();
unsigned short getYear() const;
private:
char singer[51];
char name[51];
unsigned int length;
unsigned short year;
};
And then in Interface:
bool isEqual(string, string);
template<typename T>
bool isSmaller(T firstElement, T secondElement);
template<typename T>
bool isGreater(T firstElement, T secondElement);
I want to create a higher order function which checks the value of the comparator function. However, one of the values which the comparator has to take has to come from a Songs object. In other words, I have to also pass one of the 4 getters, depending on the situation.
You want to use member function pointers. And here's an simple example of a generic higher order function:
template <typename T, typename Func>
void Call(T* obj, Func T::* memFuncPtr)
{
(obj->*memFuncPtr)();
}
Call accepts a generic object pointer and a pointer to a member function of that object's class and simply calls that function. For example,
class A
{
public:
void foo()
{
cout<<"A::foo() called\n";
}
void bar()
{
cout<<"A::bar() called\n";
}
};
int main()
{
A a;
Call(&a, &A::foo);
return 0;
}
In addition to member function pointers, the Boost.FunctionTypes library gives you a handle on the functions signature. These techniques should be a good starting point.
Note that if you didn't want to use templates, you can write out a non-generic definition, by specifying both the object type and the member function signature.
void CallA(A* obj, void (A::*)() memFuncPtrOfA)
{
(obj->*memFuncPtr)();
}
Since both A::foo and A::bar satisfy the function signature in CallA's second argument, you can call them both:
A a;
CallA(&a, &A::foo);
CallA(&a, &A::bar);

Two Classes (A,B) - B to have a pointer to class A non-static method

I have two classes that don't know anything about themselfs class A, class B.
Class A is called the ENGINE,
Class B is called the GUI.
I want GUI class to have a pointer to a function in class ENGINE, so that when an event occurs on GUIControl, it calls ENGINE member function with two parameters (int,int).
Here's how i would like to have it:
class CGUIManager
{
public:
void SetControlCallback(void(*pFunctionPointer)(int,int) );
private:
void (*m_pControlCallbackFunction)(int,int) ;
};
void CGUIManager::SetControlCallback(void(*pFunctionPointer)(int,int) )
{
if(pFunctionPointer)
m_pControlCallbackFunction = pFunctionPointer;
}
class CEngine
{
private:
void GUIControlsCallback(int iControlID, int iControlMessage);
CGUIManager *pGUI;
};
Now while initializing ENGINE, i want to call:
//Set Controls Callback to CEngine Method
pGUI->SetControlsCallback( GUIControlsCallback );
To register a callback within CGUIManager class, that points to a method in CEngine class.
How can i do that?
Thanks in advance.
I would suggest using an interface (or something like that) if you would like it to be oo instead of function pointers ( which must point to a static member btw )
class IGuiCallback
{
public:
virtual void GUIControlsCallback(int iControlID, int iControlMessage)=0;
};
class CGUIManager
{
public:
void SetControlCallback(IGuiCallback*);
private:
IGuiCallback* m_pCallback;
};
class CEngine:public IGuiCallback
{
public:
void GUIControlsCallback(int iControlID, int iControlMessage);
private:
CGUIManager *pGUI;
};
then in engine:
pGUI->SetCallback(this);
There may be some syntax errors in my code but you should get the picture
Pointers-to-member-functions are not function pointers in C++.
To call your callback later (using provided SetControlsCallback signature), the caller need to have a valid instance of CEngine. You can achieve that by binding the pointer to CEngine to GUIControlsCallback:
CEngine* pEngine; // initialized somewhere
pGUI->SetControlsCallback(std::bind1st(pEngine, GUIControlsCallback));
If you use Boost or C++11, you'd better use their versions of bindings (boost::bind or std::bind respectively).
The easiest approach is to use std::function<void(int, int) as the type of the registered callback: this object can be used to call any function [object] which is callable with two ints. In particular, it could call the member function CEngine::GUIControlsCallback(int, int) which actually has three parameters:
the two obvious parameter to the member function of type int
the implicit pointer to the object (which becomes this)
The way this is done is to construct a function object which provides as first parameter a pointer to the CEngine object and takes two integers:
struct CEngine_bind {
CEngine_bind(CEngine* engine): engine_(engine) {}
void operator()(int i0, int i1) { this->engine_->GUIControlsCallback(i0, i1); }
CEngine* engine_;
};
Alternatively, you can use std:bind() which is a create a suitably bound function:
CEngine engine; // ... wherever this object is coming from)
std::function<void(int, int)> callback(std::bind(&CEngine::GUIControlsCallback, &engine,
std::placeholders::_1, std::placeholders::_2));
... and then set the callback object as the callback. This object simply be called passing two integer parameters which will cause the member function on the referenced object to be called:
callback(10, 20);
would call
engine.GUIControlsCallback(10, 20);
The std::function<void(int, int)> is copyable, i.e. you can easily store it in your CGUIManager class.
If you are able to change the interface of the CGUIManager class, I ssugest you generalise it to use boost::function<void(int, int)> (or std::function if writing in C++11) instead of a function pointer.
If you can't, unfortunately you are a victim of bad design. C-style callbacks that use function pointers usually allow for some kind of void* user data parameter to carry any additional information bound to the callback - in this case the your CEngine pointer could be cast to void* and a free function wrapper could be written to cast the void* back to CEngine. However, if you are able to change the callback interface, using boost/STL function is a superior technique.

Use class member functions as callbacks?

I would need a member function to be passed into a third party external method:
box_self_intersection_d(mycallback);
The box_self_intersection_d is a third party external static method, and I cannot modify it. mycallback is a method I want to pass it into the box_self_intersection_d, it is a class function and is accessing some members in this class ( have full control for this class and the mycallback)
Is there anyway I can use class member functions as callbacks without declaring them as static functions?
Edit: the signature of mycallback is (const box &boxA, const box &boxB), where box is a special class from the third party provider.
And the signature for box_self_intersection_d is
void box_self_intersection_d(RandomAccessIterator begin,RandomAccessIterator end,Callback callback)
If the function box_self_intersection_d takes a functional as parameters, and mycallback is a method of a class MyClass, you can use boost::bind:
box_self_intersection_d( boost::bind( &MyClass::mycallback, myClassInstance ) );
where myClassInstance is the instance of the class MyClass.
If the callback accepts a void* for user-defined data, you can use a static wrapper function that casts the void* argument to the class type and calls your member function.
Example:
static void Foo::callback_method(void* data) {
static_cast<Foo*>(data)->mycallback();
}
void Foo::register_my_callback() {
box_self_intersection_d(&Foo::callback_method, this);
}
Most sane callback libraries allow you to pass this void* argument to the functions as a way to have user-defined data in it. If not, you'll need to resort to the dirty method:
static Foo* Foo::callback_object;
static void Foo::callback_method() {
callback_object->mycallback();
}
void Foo::register_my_callback() {
callback_object = this;
box_self_intersection_d(&Foo::callback_method);
}
In general, if you need to pass a function, there is just no other way: Either you have a data side-channel like the void*, which your library provider seems to have omitted (and is clearly a bug in the library), or you need to transport the this pointer via a global variable.
There are a couple of possible workarounds. You can have a look here: http://www.newty.de/fpt/callback.html#member
In short, you can either:
declare a static "wrapper method" and pass the instance of the class to it,
or else store a pointer to the object as a global variable.
Hope that helps,
You haven't provided the signature box_self_intersection_d()
in general, if the signature is
void box_self_intersection_d( void *cb );
or even
void box_self_intersection_d( void (*cb)(const box&, const box&) );
then you cannot pass it a pointer to a member function.
The reason is that sizeof(a_member_function) is different than
sizeof(a_function_pointer). If this is the case, I think you are forced to use thiton's solution, and create a static function.
Since it's CGAL, the callback is actually a template parameter.
Its only constraints are "Callback must be of the BinaryFunction concept".
That is, it can be anything that is "callable" with the proper parameters.
This includes any object with a void operator() (const box&, const box&) member function.
Implementing that function in your class and passing *this for the callback would probably be the simplest solution.
There is a horrible solution that I can conceive of that means copying/pushing 'this' and function code to the calling stack, (or some other caller-allocated segment that can be made writeable and executable), and passing the address of the function to the library. The called-back function could then find its own code address, extract 'this' using an offset/pointer arith. and call a member function. Should work for multiple threads.
I hereby claim this years 'Gruesome Hack' award for a solution that makes developers feel physically ill but might still actually work if a project manager is pointing a shotgun at your head.
Rgds,
Martin

C++: member function address (function pointers)

I have a class X which has this method:
void setRxHandler(void (*h)(int));
And I want to pass to it a member function that exists in instances of class Y.
void comm_rxHandler(int status);
I tried the following:
x.setRxHandler(comm_rxHandler)
But it get the following compile error (I'm using Qt):
error: no matching function for call to
‘X::setRxHandler(< unresolved overloaded function type>)’
So, how can I do that?
I noticed if I declare comm_rxHandler (class Y) as static, I have no errors. But I want comm_rxHandler as a non-static method. Also I want setRxHandler method (class X) to be generic and not class-specific. So I can't declare that method as:
setRxHandler(void (Y::*h)(int))
How to do that? Can you help me on this?
Thanks!
C++ doesn't support bound methods. To invoke a member function through a function pointer, you need to have two things: an instance of the class and the function pointer.
So setRxHandler(void (Y::*h)(int)) is almost correct. You need to declare it as:
void setRxHandler(Y*, void (Y::*h)(int));
To invoke setRxHandler(), you need to pass it arguments as follows:
Y y;
setRxHandler(&y, &Y::comm_rxHandler);
In the setRxHandler() method, you can invoke the function pointer using this syntax:
void setRxHandler ( Y* y, void (Y::*h)(int) )
{
// ...
(y->*h)(0);
// ...
}
To make generic, you need to abstract the Y parameter away, but this is difficult to get right. Check out Boost.Function for an existing implementation that supports this use case, and many more.
Change your callback to this:
void setRxHandler(std::function(<void(int)>);
Then you can use binders:
setRxHandler( std::bind(&class_name::comm_rxHandler, obj) );
(std::function and std::bind are part of the upcomming next version of the C++ standard. It's quite likely your compiler already comes with them. If not, they might live in namespace std::tr1. If all else fails, you will find them at boost - which is where they were invented - as boost::function and boost::bind.)
You can, however, also pass non-member or static functions to setRxHandler, as well as function objects (which is the result of std::bind).
If your compiler already supports lambda functions (also part of the next standard, but already supported by, e.g., recent versions of GCC and VC), you can also use one of those:
setRxHandler( [](){obj.comm_rxHandler();} );
As it is now, the setRxHandler prototype takes a pointer to a function that doesn't return anything and takes an int. As you have noticed, this won't work with member functions because they can't be called like a normal function (you have to handle the this pointer as well, which means having an instance of that class to call the method on).
To make it both work with member functions and non-specific (generic), you have to either make a base class and have all classes you want to use setRxHandler with derive from that class:
class Base { ... };
class Derived : public Base { ... };
// then for the prototype
void setRxHandler(void (Base::*h)(int)) { ... }
// and you can use setRxHandler for all types that derive from Base, which gives you more control than the second option, which is:
or use templates:
template<typename T>
void setRxHandler(void (T::*h)(int)) { ... }
With the template option, you really have no control over what class will be used with setRxHandler (excluding RTTI), which can be exactly what you want.
You can either make a base class for Y and use that (to avoid being "class specific"), or use templates:
template <class T>
setRxHandler(void (T::*h)(int));
But then this may raise questions of how to use the member function (you tell us if it does).
As others have already mentioned, C++ does not provide this functionality.
Another option you could use is libsigc++ which is widely used in gtkmm, see this example in their tutorial for instance on how to pass pointers to member-functions. Your example could look something like:
// sigc::slot<void, int> is a 'slot' to hold a function with return type void
// and 1 int argument.
void setRxHandler(sigc::slot<void, int> slot);
void comm_rxHandler(int status);
//sigc::mem_fun() can convert a member function to a function slot.
x.setRxHandler(sigc::mem_fun(*this, &X::comm_rxHandler));

Function pointer in parameter

I need to make a function which adds a function pointer to map. It would be something like this:
bool RegisterFunction (string name, FunctionPointer function).
But I have problem with calling it, because I don't know how to pass function to it instead of result of function (when I call this as here:
RegisterFunction ("run", Run())
it doesn't works, neither works Run without parentheses, nor:
*Run()
&Run()
*Run
&Run
How to fix this?
Edit:
The error is:
parser.cpp|9|error: no matching function for call to
'MCXJS::Parser::RegisterFunction(const char [4], <unresolved overloaded function type>)'|
The RegisterFunction() and Run() functions are in Parser class, which is in MCXJS namespace.
Class body is:
class Parser
{
public:
Parser ();
CVariable RegisterFunction (FunctionPointer);
bool RegisterErrorHandler (ErrorType, ErrorHandlerPointer);
CVariable Run (std::string);
bool AlwaysDefaultErrorHandler;
int MaxCallStackSize;
private:
std::map <std::string, FunctionPointer> ExternalFunctions;
std::map <ErrorType, ErrorHandlerPointer> ErrorHandlers;
ErrorHandlerPointer DefaultErrorHandler;
};
And the parser.cpp file:
Parser::Parser ():
AlwaysDefaultErrorHandler (true), MaxCallStackSize (4)
{
RegisterFunction ("run", Run);
};
CVariable Parser::Run (std::string path)
{
return 5;
};
Typedefs:
typedef CVariable (*FunctionPointer) (std::string);
typedef void (*ErrorHandlerPointer) (ErrorData);
Run is a non-static member function, not a normal function so either you are registering something of the wrong type or you need to change your typedef to refer to a pointer-to-member.
E.g.
typedef CVariable (Parser::*FunctionPointer) (std::string);
Then the correct way to form a pointer-to-member would be:
RegisterFunction("run", &Parser::Run);
Note that you have to use either the .* or ->* operator with an object or object pointer respectively to call the member function through the pointer-to-member.
RegisterFunction ("run", Run)
is the correct method. What error are you getting using that?
I suspect that the problem is not with how you are calling RegisterFunction, but with how you are defining it. You give us this:
RegisterFunction (string name, FunctionPointer function).
but leave out the declaration of FunctionPointer. It would need to be defined something like:
typedef void (*FunctionPointer)()
Assuming that Run is defined as:
void Run();
Note that for this to work, All of the functions you use with RegisterFunction must have the same signature.
UPDATE: Based on the error message you provided in the comment, it seem the problem is that you have more than one "Run" function, and the compiler don't know which one you want to pass. (Unfortunately, I'm not sure how you clarify it, so you may wish to rename one of them)
One thing you may want to try is:
RegisterFunction (std::string("run"), Run);
Given an exact match for the first parameter, it may be able to choose which Run function based on which matches the signature in FunctionPointer.
UPDATE2 :
You will either need to make Parser::Run() a static function, are change the declaration of FunctionPointer to:
typedef CVariable (Parser::*FunctionPointer) (std::string);
You can just pass the name of the function without any decoration or any parentheses:
RegisterFunction(name, Run);
However, the following should also work:
RegisterFunction(name, &Run);