I'm trying to create an array of function pointers in C++ that I can use as a jump table. The functions are all prototyped like
void(unsigned char*, int, int)
So I thought I would do
typedef void (*func)(unsighed char*, int, int);
and then
func tfunc[256];
And then set the individual elements like this:
tfunc[0]=func01;
But then I get "function call missing argument list; use '&myclass::func01'"
But then when I try
tfunc[0]=&myclass::func0;
I get "error C2440: '=' : cannot convert from 'void (__thiscall myclass::* )(unsigned char *,int,int)' to 'myclass::tfunc'
1> There is no context in which this conversion is possible
I am confused.
I think I fixed it by adding MyClass:: in the header: tyepdef void (MyClass::*func...);
You could use std::function<void(unsigned char*, int, int)> for your array of functions and appropriately bind your object using std::bind():
using namespace std::placeholders;
std::function<void(unsigned char*, int, int)> tfunc[256];
tfunc[0] = std::bind(&myclass::func0, this, _1, _2, _3);
Using std::function<Signature> is nicer than using function pointers in all cases because it allows to pass through necessary context, e.g., a pointer to an object. If you really mean to just call the function and you don't need an object, you can still use std::function<...> and you made your func0 member static instead. In that case you could still use std::bind() but it isn't really needed:
struct myclass {
static void func0(unsigned char*, int, int);
};
// ...
tfunc[0] = std::bind(&myclass::func0, _1, _2, _3);
tfunc[0] = &myclass::func0;
For the fans of dynamic polymorphism: internally std::function<...> has an inheritance hierarchy and any concrete initialization instantiates a derived class as needed. The only real differences are that you don't need to faff about creating a hierarchy and some implementations do clever things to make it more efficient.
Even though you have an array of pointers to {static} functions or pointers to members, you will still need to pass the parameters when you call the function:
(*vector_of_functions[i])(param1, param2, param3);
The above is for standalone functions. Executing a member via pointer to member method is left as an exercise to the reader (hint: See C++ faq pointer to member).
If you want to put a class member function into your array, the class member function should be declared static.
In case your class member function is not static, than you have to "bind" this to it, and it forces you to use the solution suggested by #Dietmar.
Related
I'm trying to define a function/method (void MyClass::myDispatcher(int, int, void *) or std::function<void(int, int, void *)> myDispatcher) which would be a member of a host class.
However, I also need to pass this function to through an external library which takes as argument: void (*dispatcher) (int, int, void *).
Is there a way I can convert a non-static function to the required void (*)(int, int, void *) type ?
My first attempt with the candidate void MyClass::myDispatcher(int, int, void *) was using the std::bind() in order to bind MyClass::myDispatcher with this. Although I could not convert the return type of std::bind to match the void (*).
The second attempt was done using std::function<void(int, int, void *)> myDispatcher for which I tried to use the reinterpret_cast<void (*)(int, int, void *)>(&myDispatcher) to fit in the requested argument. It did compile but I ultimatly ended up in a segfault within the external library.
I could summarized my two attempts with this example:
class MyClass{
MyClass() = default;
void myDispatcher(int, int, void *){
// do something
}
void init(){
myFct = [this](int, int, void*){
// do something
};
external_function(reinterpret_cast<void (*)(int, int, void *)>(&myFct));
// or the non-compiling
// external_function(std::bind(&MyClass::myDispatcher, this));
}
private:
std::function<void(int, int, void*)> myFct;
};
Edit:
As some of you pointed out: this C-style external_function has an extra void * argumement which is passed as the last arg to the provided function!
To summarise: there is no way to do such a thing since there is a fundamental difference between a function pointer and non-static member functions. However, C-style library usually provides a workaround which performs a callback to the provided static function:
void external_function(void (*dispatcher) (int, int, void *), void* info){
// a bunch of instructions (meaningless for this example)
int a,b;
dispatcher(a,b,info);
}
Once we know that, one can cast back the info pointer to the class we want.
As stated, this is not possible since there is no way to meaningfully construct a plain function pointer from a (non static) method, a closure, or a std::function object.
Roughly speaking, each of the constructs above are logically formed by two parts: some fixed code (a pointer to a fixed, statically known function), and variable data (the object at hand, or the captures for a closure). We can not simply throw away the second part.
That being said, I would recommend to check if the library will call the dispatcher passing a user-defined pointer for its void * argument. It's somewhat common to see C style library functions like
void register_callback(void (*dispatcher)(int,int,void *), void *user_data);
This is a trick to allow to simulate closures in C, passing the two "parts" of the closure separately.
If that's the case, instead of
// not working, just for example
std::function<void(int, int)> f;
register_callback(f);
You can write
// Make sure f will live long enough.
// I'm using new to stress the point, but you can use anything
// else provided that the pointer will be valid when f is
// called.
std::function<void(int, int)> *pf = new ...;
register_callback(call_the_function, pf);
provided you have defined
// fixed function, independent from the std::function object
void call_the_function(int x, int y, void *p) {
std::function<void(int,int)> *pf =
(std::function<void(int,int)>*) p;
(*pf)(x,y);
}
If you used new to keep the pointer valid long enough, remember to delete it when the callback is no longer needed.
Is there a way I can convert a non-static function to the required void (*)(int, int, void *) type ?
No, there isn't. A function pointer cannot point to non-static member functions, nor to function wrapper objects.
What you can do, is point to a normal function that in turn calls the member function. The challenge is getting the instance into that function. Most C callback API allow passing user defined data into the callback in form of a pointer to void, in which case this isn't a problem. If there is no such option, then you can only use a globally accessible instance, or an instance that is created within the callback.
You will need to read the documentation of the API to find if and how passing user data is possible. There is a void* parameter in the callback, which hints that it may be what you need.
No you can't get a void (*)(int, int, void *) from a non-static member function. Non-static member function are fundametally different from free functions: You need an object to call the method.
However, in your code you are already using std::function and std::function has a constructor to convert a void (Foo::*)(int, int,void*) to a std::function<void(Foo*,int,int,void*)>.
The external library expects a C style function pointer. I't won't accept C++ callable objects (e.g. std::function or std::bind). You have to wrap the C++ callable objects inside a plain function with the required signature. Something like this:
void dispatcher(int theInt1, int theInt2, void *theData) {
theInstanceOfMyClass.myDispatcher(theInt1, theInt2, data);
}
You might want to pass the address of your C++ instance as the third argument, e.g.:
void dispatcher(int theInt1, int theInt2, void *theData) {
static_cast<MyClass *>(theData)->myDispatcher(theInt1, theInt2, data);
}
I'm trying to declare a method typedef which includes a pointer parameter of the method type itself - is this possible?
A method would look something like:
void myFunc(FuncType* pFunc, int a) {}
where myFunc is a declaration that matches FuncType, so I could set a variable and call it like this:
FuncType f = myFunc;
f(&f, 5);
I've tried to declare a typedef matching this method as:
typedef void (*FuncType)(FuncType*, int);
But this doesn't work because FuncType is required before it is fully declared. I can fix this by setting the parameter to a void pointer, but is there some way around this; perhaps through some form of forward declaration of FuncType?
This is impossible; a function can't take a parameter of its own type (or return such a thing).
This is the case for all reasonably powerful type systems.
The only workaround is to introduce an indirection through another type, as you did with void*.
It's analogous to how a class can't contain an instance of itself as a member, which you work around by indirecting through a pointer or reference.
Not only can you NOT declare such a typedef, you cannot declare such a function either. It results in infinite recursion.
Here's how such a function declaration would look like:
void myFunc(void (*pFunc)(...), int a);
where ... would expand to:
void (*pFunc)(...), int)
where ... would expand to:
void (*pFunc)(...), int)
I have a set of functions called in a common interface, and I store those function pointers in a common container, so I have
typedef void(*CommandFunction)(const InputArgsMap &, const ArgumentMap *);
With this said, what is the best way to declare functions of this type without copy-pasting the argument list? I thought of implementing this via a #define, but is there any other (better, oop) way?
For instance, is it possible to do something like
#define CMD_ARGS (const InputArgsMap &, const ArgumentMap *)
void _fcn_1(CMD_ARGS);
void _fnc_2(CMD_ARGS);
If you declare a function, rather than pointer, type alias
typedef void CommandFunction(const InputArgsMap &, const ArgumentMap *);
then you can use it to declare functions
CommandFunction _fcn_1;
CommandFunction _fcn_2;
You'll still need to write out the parameter list when you define them.
is there any other (better, oop) way?
Overriding a virtual member function of an abstract interface might be nicer, depending on exactly what you're doing. You will have to duplicate the parameter list if you do that, which you seem to find distasteful; but in modern C++ you can at least use the override specifier to make sure you get that right.
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.
I am trying to store pointers to memberfunctions of different Classes in C++. What are the possibilities in C++?
I would like to do this:
class A {
T0 f(T1,T2);
};
class B {
T0 g(T1,T2);
T0 h(T1,T2); //interfaces cant be used since the number of functions per class differs.
};
typedef WHATTOPUTHERE type;
type x;
x = A::f;
x = B::h;
Update: Another Problem is that the code should be continueable like this:
B myB;
myB::x(a,b); //not sure about the syntax, should result in myB::h(a,b) being called
This means that I can not bind at the time I store the pointer, since the instance does not exist (yet).
Function objects to encapsulate your function pointers should work.
boost::function is one option, maybe something like this:
class SomeObj
{
public:
void SetInt(int i);
};
SomeObj myObject;
std::vector<boost::function> memberFuncs;
// in the template arg to boost::bind specify the function type
// _1 here denotes late binding so you can pass whatever value you want when invoked
// you could simply bind a parameter as a variable or literal instead
memberFuncs.push_back(boost::bind<void(int)>(&SomeObj::SetInt, &myObject, _1));
memberFuncs[0](42); // myObject->SetInt(42);
Untested/uncompiled code disclaimer this is just for a general idea.
One possible implementation (using C++11) can easily be done using std::function and a lambda like this:
typedef std::function<void(int)> FunctionType;
SomeClass someClass;
FunctionType func = [&someClass](int argument)
{
someClass.SomeMemberFunction(argument);
};
To have a pointer to Fred::f(char, float) you need this sort of pointer:
int (Fred::*)(char,float)
http://www.parashift.com/c++-faq-lite/pointers-to-members.html
The answer to your particular question is that there is no type that you can add to the typedef and make the code compile. The reason is that member function pointers take a hidden argument of the type of the class form which they are obtained. The type of that hidden argument will be different when you take the address of a member function from A or B.
The next question is whether it makes sense or not from a design perspective, considering that you cannot apply the function pointer A::f to an instance of type B, what is the point of considering member pointers of A and B together?
Now, there are possible workarounds for this particular problem (if it makes sense in your case, but I would first review the design) that involve performing type-erasure on the function pointer to remove the hidden argument and generate an object that is callable with the given set of arguments and return type that is common to all of the member functions. This is already done inside std::function (alternatively boost::function if your compiler does not support C++11), as has been suggested before:
A a_instance;
std::function< T0 (T1,T2) > f( std::bind( &A::f, &a_instance, _1, _2 ) );
T0 r = f( T1(), T2() );
Note that part of the trick is that std::bind binds the member function pointer with the pointer to the instance, filling in the hidden argument, while leaving the other two arguments unbound. At this point, because the result of bind does no longer depend on the type of the first argument, type-erasure can be applied removing A from the type of the resulting object.