Passing a void function as an argument to another function - c++

I'm trying to pass a void function to another void function, unsuccessfully so far. So I created this function inside the class called ExitButton like this. ExitButton.h:
class ExitButton{
void setup(void (*_setup));
};
Then I include that class into another class like this. ofApp.h:
include "ExitButton.h"
class ofApp : public ofBaseApp{
void update();
void setup();
StartButton *startButton;
}
So in my ofApp.cpp I want to call the update function like this:
void ofApp::update(){
exitButton->setup(setup()); // This throws me the following error: Cannot initialize a parameter of type 'void (*)' with an rvalue of type void
}
So I assume, I can only pass a void function that is a pointer?
Is it actually possible to pass a void function as a parameter to another function?

This is probably what you want:
#include <iostream>
using namespace std;
class ExitButton{
public:
void setup(void (*_setup)())
{
_setup(); // we call the function pointer
};
};
void setup() // this is a void function
{
cout << "calling void setup()" << endl;
}
int main()
{
ExitButton eb;
eb.setup(setup); // use a void function as a parameter
}

Related

How to Pass a Function to Structure in C++?

My Struct Code :
struct MouseHandler
{
void OnHover();
void* OnLeftClick();
// void (*OnLeftClick)();
void OnRightClick();
void OnDrag();
void OnDrop();
};
Calling of Struct :
MouseHandler ms;
I am trying to pass SampleScrollDownClickHandler to ms.OnRightClick(), Is it is possible, How can I do that, I am tried this, but I failed :
ms.OnRightClick() = SampleScrollDownClickHandler();
I am not using std library!
So the commented out line is actually closer to the solution you want. In order to pass the function pointer you need to not call the function itself, which you did by invoking it with the trailing (). So the following code is closer to what you want (limiting it just to the most basic parts of your code):
struct MouseHandler {
void (*OnLeftClick)();
void OnRightClick();
void OnDrag();
void OnDrop();
};
void my_callback() {
}
int main() {
MouseHandler m;
m.OnLeftClick = my_callback;
}
The member variables of the struct are not defined correctly.
void OnHover(); declares a member function, not a member variable. You need to use void (*onHover)();, which can point to a non-member function.
struct MouseHandler
{
void (*OnHover)();
void (*OnLeftClick)();
void (*OnRightClick)();
void (*OnDrag)();
void (*OnDrop)();
};
With that change, you can use:
MouseHandler me;
me.OnRightClick = SampleScrollDownClickHandler;
as long as SampleScrollDownClickHandler is declared and is the right function type.

How to pass function pointer (callback) and call it without knowing it's type?

I have a function pointer as a member to a pure virtual base class. I'd like to pass this pointer to a library which does not know about either of these classes, MyBase or MyClass, and then call the function pointer as a callback into MyClass. I'm writing the lib as well. I want the shared library to call a callback in MyClass.
My question is, how does one pass a function pointer as an argument to a function and have it called without knowing anything about the class itself.
I was considering a pointer to a function pointer, but wasn't sure how to cast properly.
class MyBase {
public:
virtual void callback() = 0;
void (MyBase::*callback_ptr)();
};
class MyClass : public MyBase {
public:
MyClass();
void callback() { cout << "callback called" << endl; };
};
main.cpp
{
MyClass my_class;
my_class->callback_ptr = &MyBase::callback;
lib->set_callback(my_class->callback_ptr);
}
lib.cpp
class MyLib {
public:
// how to declare the member function pointer here?
void** callback_ptr;
// how to write sig here?
set_callback(ptr) { callback_ptr = ptr }
running() {
// how to call the callback here w/o knowing it's type?
}
}
#include <iostream>
#include <functional>
using namespace std;
class Foo {
public:
void myFunction() {
cout << "Foo::myFunction()\n";
}
};
void myAPICall(std::function<void()> arg) {
arg();
}
int main(int, char**) {
Foo foo;
// Using a lambda
myAPICall( [&]() { foo.myFunction(); } );
// Using bind
myAPICall( std::bind(&Foo::myFunction, foo) );
return 0;
}
Yields:
$ g++ -std=c++11 f.cpp -o f && f
Foo::myFunction()
Foo::myFunction()
This assumes that you control the API you're calling, and it uses std::function like my code does. If it accepts a C-style function pointer rather than std::function, then you're going to have to play much different games.
To get a function pointer when you don't know the exact type of function that will be called, use std::function from the <functional> header.
class MyLib {
public:
// how to declare the member function pointer here?
std::function<void()> callback_ptr;
// how to write sig here?
void set_callback(std::function<void()> ptr) { callback_ptr = ptr; }
void running() {
callback_ptr();
}
};
To use a member function as a std::function, use std::bind:
int main()
{
MyClass my_class;
MyLib my_lib;
my_lib.set_callback(std::bind(&MyClass::callback, &my_class));
my_lib.running(); // calls my_class.callback()
}

Passing non-static member function as argument to a member function in a different class

UPDATE I realize this question's lacking a proper MCVE, it will take me some time to come up with one. I will update it when I have time to come back to this, sorry. I appreciate the answers thus far.
Following this answer regarding static functions:
Declaration (in MyClass)
void MyClass::func ( void (MyOtherClass::*f)(int) ); //Use of undeclared identifier 'MyOtherClass'
Example of function being passed to func:
void MyOtherClass::print ( int x ) {
printf("%d\n", x);
}
Function call (in MyOtherClass)
void MyOtherClass::loop(){
func(&MyOtherClass::print);
}
How can one pass a member function as a parameter of a member function of another class?
According to the ISO, the answer is "don't". Unlike normal functions, a non-static member function is meaningless without an instance of the class. As a workaround, you can have your calling function take a std::function and pass it a lambda.
Example:
void calling_func(std::function<void()> f);
struct foo
{
void func();
void call()
{
calling_func([this]{
func();
});
}
};
can't you just use std::function and std::bind to that?
class MyOtherClass
{
public:
MyOtherClass() {}
void print(int x)
{
printf("%d\n", x);
}
};
class MyClass
{
private:
std::function<void()> CallbackFunc;
public:
MyClass() {};
void AssignFunction(std::function<void(int)> callback, int val)
{
CallbackFunc = std::bind(callback, val); //bind it again so that callback function gets the integer.
}
void DoCallback()
{
CallbackFunc(); //we can then just call the callback .this will, call myOtherClass::print(4)
}
};
int main()
{
MyClass myObject;
MyOtherClass myOtherObject;
int printval = 4;
//assign the myObject.callbackfunc with the myOtherClass::print()
myObject.AssignFunction(std::bind(&MyOtherClass::print, myOtherObject,std::placeholders::_1), 4);
//calling the doCallback. which calls the assigned function.
myObject.DoCallback();
return 0;
}

Passing member function to another object's member function C++

I am having issues trying to pass a function as an argument in another object's function. I am well aware there are many similar topics but I either can't get their solution to work or can't understand them.
class foo
{
public:
void func1(void (*Drawing)(void));
template<class T>
void func2(void (T::*Drawing)(void));
};
class bar
{
private:
foo myFoo;
void Drawing();
void func3() {
// Attempt 1
myFoo.func1(Drawing);
// Attempt 2
myFoo.func2<bar>(&bar::Drawing);
}
};
So in my first attempt, I get the error where you can't convert void (bar::*)(void) to void (*)(void) of which I then found out there are normal function pointers and member function pointers.
Attempt 2 was my feeble attempt to overcome this but I get unresolved externals now...
So how can I successfully pass my Drawing() member function into another function from another object?
The issue is that you cannot consider bar::Drawing as a void (*)(void) function since it's a non static method, which therefore required an object (the this context which will be used)
A solution, assuming c++11 is ok for you, would be to use std::bind and to sligtly modify your foo definition:
class foo
{
public:
void func1(std::function<void(void)> Drawing)
{
Drawing(); // or do whatever you want with it
}
};
Then you will be able to do
void bar::func3() {
myFoo.func1(std::bind(&bar::Drawing, this));
}
making valid a lot of potential uses
int main()
{
bar myBar;
myBar.func3();
foo myFoo;
myFoo.func1([](){ printf("test\n"); });
return 0;
}
I'm guessing you've left out important details as to what you're trying to accomplish. However, the following should give you some idea of what you need to do.
Code
#include <iostream>
class foo
{
public:
void func1(void (*Drawing)(void))
{
std::cout << "func1\n";
}
template<class T>
void func2(T* instance, void (T::*fn)(void))
{
std::cout << "func2: ";
(instance->*fn)();
}
};
class bar
{
public:
bar()
{
func3();
}
private:
foo myFoo;
void Drawing()
{
std::cout << "bar::Drawing()\n";
}
void func3()
{
// Attempt 1
//myFoo.func1(Drawing); // This won't work
// Attempt 2
myFoo.func2(this, &bar::Drawing); // Must pass an object instance if you plan to use the member function
}
};
int main(int argc, char *argv[])
{
bar b;
return 0;
}
Sample Output
func2: bar::Drawing()

Passing a function pointer to a function

What should I do if I want to pass a non-static member function of any class as a click function of the button ? Is it possible ? If so what do I need to do ? For example in which ever class (EntityToolGUI over here) the button is initiatlized, I want to set its click action to a non-static member function (a non-static member function of class EntityToolGUI ) of that class.
GUIButton.h
typedef void (*ptr2clickFunc)(void);
class GUIButton : public GUIObject {
private : void (*clickFunc)(void);
public : void setClickFunction(ptr2clickFunc clickFunc);
};
GUIButton.cpp
void GUIButton::setClickFunction(ptr2clickFunc clickFunc)
{
this->clickFunc = clickFunc;
}
EntityToolGUI.h
class EntityToolGUI {
public : EntityToolGUI();
protected : void addAnimation();
}
EntityToolGUI.cpp
void EntityToolGUI::addAnimation()
{
cout<<"add animation"<<endl;
}
EntityToolGUI::EntityToolGUI()
{
....
btnAddAnimation->setClickFunction(&EntityToolGUI::addAnimation);
}
I am getting an error no matching function call to GUIButton::setClickFunction(void (EntityToolGUI::*)())
candidate is void GUIButton::setClickFunction(void (*)())
How do I solve this ?
Most (decent) C code that passes function pointers around use an extra void* argument for passing user context to the function. This is not so common in C++ (as better techniques than function pointers exist), but if you're stuck using function pointers for some reason then it may be appropriate.
typedef void (*ptr2clickFunc)(void*);
class GUIButton : public GUIObject {
private : ptr2clickFunc clickFunc;
private : void * userdata;
public : void setClickFunction(ptr2clickFunc clickFunc, void* userdata);
};
class Foo
{
static void do_foo( void * userdata )
{
Foo* thisptr = static_cast<Foo*>(userdata);
thisptr->foo();
}
void foo() { ... }
};
int main()
{
Foo foo;
GUIButton button;
button.setClickFunction( &Foo::do_foo, &foo );
button.click();
}
EDIT As noted by Bartek, if you're doing this a lot you can extract the static function into a template - it looks a bit like this (untested and probably with minor errrors).
// GUIButton is as before
// Note no static function here
class Foo { void foo(); }
template<typename T, void(T::*FN)() >
void Call( void * data)
{
static_cast<T*>(data)->*FN();
}
int main()
{
Foo f;
GUIButton button;
button.setClickFunction( &Call<Foo,&Foo::foo>, &f );
button.click();
}
If you want to pass obj fun ptr you can use boost::bind and boost::function
http://www.boost.org/doc/libs/1_50_0/libs/bind/bind.html
You cannot pass a pointer to non-static member function as a pointer to a "regular" non-member function. You should either make addAnimation static, or make ptr2clickFunc typedef a pointer to member function.
Note that invoking a pointer to member function is different from invoking a function pointer, because you must supply an instance on which the member pointer is to be invoked.
addAnimation needs to be static function. When the call back function is set the way you are doing it now, the object of class EntityTollGUI is not registered along with the function.
Try this one (C++11):
#include <stdio.h>
#include <stdlib.h>
#include <functional>
class Raiser
{
public:
std::function<void(int)> ev1, ev2;
void RaiseEv1()
{
if (!ev1._Empty())
ev1(44);
}
void RaiseEv2()
{
if (!ev2._Empty())
ev2(66);
}
};
class Handler
{
private:
int id;
std::function<void(int)> h;
public:
Handler(int newId)
{
id = newId;
h = [this](int i)
{
printf("Handler with id = %d captured event!\n", this->GetId());
};
}
void Hook1(Raiser & raiser)
{
raiser.ev1 = h;
}
void Hook2(Raiser & raiser)
{
raiser.ev2 = h;
}
int GetId()
{
return id;
}
};
int main(int argc, char * argv[])
{
Raiser raiser;
Handler handler1(1), handler2(2);
handler1.Hook1(raiser);
handler2.Hook2(raiser);
raiser.RaiseEv1();
raiser.RaiseEv2();
getchar();
}
AFAIK, this is the most you can get with events in C++ without using language extensions.