Passing function as parameter

I would like to do this:

Passing function name as parameter, C++

But the given example doesn’t work in OpenFrameworks
Any thoughts?

S

Could you post the code that doesn’t work? OF is just C++ so you can pass pointers to functions around if you want to.

Sure

void ofApp::myOtherFunction() {
cout << endl << "And this is the result.";
}

void ofApp::myFunction(void (*otherFunction)(), char parameter[80]) {
cout << parameter;
(*otherFunction)();
}

and in draw()

myFunction(&ofApp::myOtherFunction, "I am calling a function with a function.");

calls a types error

… you are declaring a function that takes… a normal function
and you are passing a function that is declared within a class

you need to change one of two…

easiest will be 2 declare your func outside ofApp.

hi,

sorry I don’t immediately understand this (probably being dim)
please can you explain in a little more detail?

Ahhh

I geddit

I was being dim, apologies

no problem

the syntax for passing a member func is this
void myFunction(void (ofApp::*otherFunction)()) {
(this->*otherFunction)();
}

keep in mind that passing member functions to other classes , sometimes means that you need to pass the class * as well…

so unless there is no other way around it just pass the class… no need to complicate things when they can be simple

well, i have it working fine as long as I drop the definitions out of ofApp, and then:

void myOtherFunction() {
cout << endl << "And this is the result.";
}

void myFunction(void (*otherFunction)(), char parameter[80]) {
    cout << parameter;
    (*otherFunction)();
}

in draw

myFunction(&myOtherFunction, "I am calling a function with a function.");

But that leads me to two questions

  • are you explaining how to have it working with the definitions within ofApp in your post above? If so, I can’t get this approach working, please can you clarify?

  • if the function in ‘myOtherFunction’ requires a parameter defined in the course of ‘myFunction’, how do I pass this to it? for example, out<<(i) where i is an int defined in myFunction.

Fingers crossed

a good way to figure this out is to study the ofSort() functions in openFrameworks
the example I gave you is very basic just to get the logic - it is better to use generic member functions with templates , otherwise, by being too specific you are not achieving anything

template<class drawClass>
    void draw(drawClass * drawC){
                drawC->draw();
    }

myrenderer->draw(this)

myrenderer->draw(&rect);

myrenderer->draw(&circle);

myrenderer->draw(&whateverClassAsLongAsItHasADrawFuncInIT);

//now with member functions directly

template<class c_l_a_s_s>
void draw(void (c_l_a_s_s::*otherFunction)()=NULL) {
void (c_l_a_s_s::*renderer)() ;
    c_l_a_s_s * t;
  renderer=  otherFunction;
    (t->*renderer)();
 }

implementation

renderer->(&whateverClass::whateverfunction)

there is everything you need to know about this
here:
http://www.newty.de/fpt/fpt.html#defi

:wink:

hope this makes sense… I think it is one of those things that once you grasp it you will see just how easy this is and use it all the time…
some things just take a while…

1 Like

hmmm, I’m trying to get my head round it and struggling!
Are there any working examples that I can pick apart?

secWin.zip (48.8 KB)

maybe it is your compiler settings not allowing this…?

I’ve made an example of creating a second OF window, and doing

secWin.draw(&ofApp::draw2);

this works both on mac and winCB

I mean, if you are looking for a 100% working example, look inside OF / lib/ of/utils/ofUtils.h

ok, fab, I get this so far - have stripped down the example to the very basics:

doSomething.zip (57.8 KB)

One question - at the minute the ‘doThis’ function passes an int along with the ‘functionToSend’

But how do I pass that int to be used in ‘functionToSend’ as it operates? For instance, setting the rectangle width?

figured it out…

doSomething.zip (68.4 KB)

:beer:

yes I owe you a few :smile:
If you look at my other thread, parallel computing, you’ll see why I wanted to do it… very happy to finally have sorted that one
many thanks!

S

Hey igiso

Wondering if you can give me another helpful pointer
As I mentioned, I used the above to wrap some parallelising (grand central dispatch) code into single function lines. Nice and tidy, or so I thought. It works well for running simple tasks concurrently…

But (always a but!) when I try to replace the simple task with some form or operation on a vector array and keep the single function line approach, I get a crash.

Do you know what might be causing this? Since I posted here yesterday I’ve adapted the sketch to test it a bit further and this shows that the problem is not apparently the concurrency code itself (as I thought yesterday). When I separate this out from being wrapped up into a single line everything runs just fine. So I’m presuming that the issue is in how I am doing the ‘wrapping’, right?

Hope you can help - here’s a zip file which includes commenting to explain the problem more clearly: concurrency2.zip (73.1 KB)

Sam

you need to share its guts as well…

you just passed the function, (scope) not the
class scope pointer…

can you make your targets global ?

remove them from ofapp class

and paste this above ofApp:

extern     vector <int> targets;
vector <int> targets;

its either that or pass a this, and access the functions from there…

the compiler uses different part of the memory to save this now so it should work…
but I don’t know if it can benefit you in your actual app.

I should clarify what I mean by “passing this”:
(without externs)
concurrency.zip (79.8 KB)

 template<class c_l_a_s_s>
    void for_all(c_l_a_s_s * doTask,void (c_l_a_s_s::*otherFunction)(int), int start, int end) {
                void (c_l_a_s_s::*with)(int) ;
                with = otherFunction;
                dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
                dispatch_apply(end-start, queue, ^(size_t blockIdx) {
                    int i = start+blockIdx;
                    (doTask->*with)(i);
                });}

so in your app you do:

    parallelise.for_all(this,&ofApp::functionA, 10,20);

now *doTask actually means something instead of being just an empty reference…

Gah, I get it now. That simples!
Many thanks again

S

1 Like