Calling funcion variable from ofApp::draw() in OpenFrameworks throws error

Hi, I want to call a function that’s a member of a class from ofApp::draw(), but it throws an error. It works if I call syst.output() from ofApp:setup() but not from ofApp::draw().

ofApp.h:

#pragma once

#include "ofMain.h"
#include "Syst.h"
#include <iostream>

class ofApp : public ofBaseApp{

	Syst system;
	using Input = float;
	   
	public:
		void setup();
		void draw();
};

ofApp.cpp:

#include "ofApp.h"

void ofApp::setup(){
	std::function<void(Input)> metaOutput = [](Input x) {
		cout << x << endl;
	};
	Syst syst = Syst(metaOutput, 10);
	system = syst;
	system.output();
}

void ofApp::draw(){
	system.output();
}

Syst.h:

#pragma once
#include "ofMain.h"
#include <functional>

using namespace std;

class Syst {

public:
	using Input = float;

	std::function<void(Input)> metaOutput;
	std::function<void()> output;
	Input input;

	Syst(std::function<void(Input)> _metaOutput, Input _input) {
		metaOutput = _metaOutput;
		input = _input;

		output = [&]() {
			metaOutput(input);
		};
	}

	Syst(){}
};

I don’t understand why it works if I call it from setup(), but not from draw(). The error has no information:

image

Hope someone with more experience know. Thank you!

Hi @Pau_Rosello , do you still have your ofApp::update() function in the ofApp class?

I removed it before posting this to have a cleaner code, but the error is the same with or without the ofApp::setup() function.

1 Like

I’m not great with std::function stuff; I love lambdas though! Did you try calling system.output() in ofApp::update() instead of ofApp::draw()? Also, what happens if you repeat the code (all of it) from ofApp::setup() in ofApp::draw()?

Edit: If I run your code I get a crash too (on linux). Then if I call system.output() in ofApp::update() instead of ofApp::draw(), it also crashes. But, if I repeat the code from ofApp::setup() in either ofApp::update() or ofApp::draw(), then the app doesn’t crash. So, I would say that something is going out of scope, or there maybe are issues with the default assignment in the Syst class that are causing the issue. Maybe? Hope this helps!

It also fails if I call it in update(). I’m using function<> because that’s the only method I know. I’m new to lambdas and pointers but if you know another method that allows me to have the same structure for the class, it will also work for me.

I edited my previous post. The line between std::function and lambdas is nuanced, so going with what you know is awesome! You have some lambdas in the code anyway! I’ll work on this a bit and see if I can figure out what is going on, and post here if I find something interesting.

My best guess is that local object syst in ofApp::setup() goes out of scope without getting properly assigned to ofApp::system. I don’t know if its because of the constructor or if an overload of operator=() is needed. The c++ rule of 3/5/0 might help clarify.

The following solution, or something similar, should work:
ofApp.h (including class Syst):

#pragma once
#include "ofMain.h"

class Syst {
public:
    using Input = float;
    // set the lambda output with the constructor, or inline  it and use a default constructor; could be const if its not going to change
    Syst(){output = [&](){metaOutput(input);};}
    // this should work OK with an argument by copy too (instead of by reference)
    inline void setMetaOutput(std::function<void(Input)>& _metaOutput) {metaOutput = _metaOutput;}
    inline void setInput(Input _input) {input = _input;}

    std::function<void()> output;

protected:
    std::function<void(Input)> metaOutput;
    Input input;
};

class ofApp : public ofBaseApp{
    using Input = float;

public:
    void setup();
    void update();
    void draw();

    void keyPressed(int key);
    void keyReleased(int key);
    void mouseMoved(int x, int y );
    void mouseDragged(int x, int y, int button);
    void mousePressed(int x, int y, int button);
    void mouseReleased(int x, int y, int button);
    void mouseEntered(int x, int y);
    void mouseExited(int x, int y);
    void windowResized(int w, int h);
    void dragEvent(ofDragInfo dragInfo);
    void gotMessage(ofMessage msg);

    Syst system;
};

ofApp.cpp:

void ofApp::setup(){
    std::function<void(Input)> tempMetaOutput = [](Input x){std::cout << x << std::endl;};
    system.setMetaOutput(tempMetaOutput);
    system.setInput(10.f);

    system.output();
}

//--------------------------------------------------------------
void ofApp::update(){
}

//--------------------------------------------------------------
void ofApp::draw(){
    system.output();
}
1 Like

Thank you! I would have been struggling with this for days… Thank you <3

1 Like