I know this thing works:
void myDisplay()
{
...
}
int main()
{
...
glutDisplayFunc(myDisplay)
...
}
so I tried to include myDisplay() function to a class that I made. Because I want to overload it in the future with a different class. However, the compiler complains that
argument of type 'void (ClassBlah::)()' does not match 'void(*)()' .
Here is the what I try to make:
class ClassBlah
{
....
void myDisplay()
....
}
......
int main()
{
...
ClassBlah blah
glutDisplayFunc(blah.myDisplay)
...
}
Does anybody knows how to fix this problem?
Firstly, there is an implicit "this" pointer in non-static member functions, so you'll need to change your void myDisplay() in ClassBlah to be static. It's awkward to work around this limitation, which is why the C++ faq lite says don't do it
Then, you should be able to pass the functions as ClassBlah::myDisplay.
Depending on your motivation for overloading (ie are you going to hotswap implementations in and out at runtime, or only at compile time?) you might consider a utility "handler" static class that contains a pointer to your base class, and delegates responsibility through that.
I ran into this problem writing a C++ Glut engine myself. Here's how I worked around it:
I placed these at the top of my program.cpp / main.cpp
// Function prototypes
void doRendering( void );
void processMouse( int, int ) ;
void processMouseClick(int button, int state, int x, int y);
void keyboardInput(unsigned char c, int x, int y);
Assign these functions to glut's callbacks here:
glutDisplayFunc(doRendering);
glutIdleFunc(doRendering);
glutPassiveMotionFunc(processMouse);
glutMotionFunc(processMouse);
glutMouseFunc(processMouseClick);
glutKeyboardFunc(keyboardInput);
Create my own class which handles these on its own and then make the contents of our static functions simply call methods on the instance of this class. Your main function should create a new instance of the class in main (in my case... App *newApp).
void doRendering( void )
{
newApp->updateScene();
newApp->drawScene();
}
void processMouse(int x, int y)
{
newApp->processMouse(x, y);
}
void processMouseClick(int button, int state, int x, int y)
{
newApp->processMouseClick(button, state, x, y);
}
void keyboardInput(unsigned char c, int x, int y)
{
newApp->keyboardInput(c, x, y);
}
Hope that explains it.
My way to solve this is simple:
First make a pointer before main function.
At the beginning of the the main function set pointer to instance of your class.
Then in new defined function for rendering, You can acces your object with global pointer.
/**
Class argon is defined in external header file.
*/
Argon *argonPtr;
void renderScene();
int main()
{
Argon argon;
argonPtr = &argon;
glutDisplayFunc( render );
}
void render()
{
RenderStuff();
argonPtr->Render();
}
Hope it works for You, for me it does.
You can use Boost bind for member functions, for example creating a thread on a member function:
class classA
{
public:
void memberThreadFunc(int i);
};
void main()
{
classA a;
boost::thread( boost::bind(&classA::memberFunc, &a, 123) );
}
You can't. glutDisplayFunc takes a parameter of type void(*)(), not void (ClassBlah::)(). Unless you're willing and able to alter the source of glut, you're out of luck.
Many C APIs that use callbacks pass a user-specified void* parameter to the callback, which you can use to store a pointer to your class. You can then pass a free function which casts the user data to a class pointer and then calls the member function. However, the way glut is designed doesn't allow that.
Related
I have the following code:
int main(int argc, char **argv)
{
App app(800, 600);
app.add_event_scene(Scene("Event Plot", event_plot));
Image x("sample.png");
struct foo { static void visual_plot() { x.draw(); } }; // Error.
app.add_visual_scene(Scene("Visual Plot", foo::visual_plot));
app.run();
return 0;
}
And I get the following error:
||=== Build: Debug in Joy-Plus-Plus (compiler: GNU GCC Compiler) ===|
G:\Development\Game-Development\CB\Joy-Plus-Plus\main.cpp|54|error: use of local variable with automatic storage from containing function|
G:\Development\Game-Development\CB\Joy-Plus-Plus\main.cpp|53|error: 'Image x' declared here|
||=== Build failed: 2 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|
I'm writing a multimedia/game engine for the Allegro 5 library, and I've abstracted the drawing part of the main-loop (As well as the event parts) into "scene" objects with plots (Functions). Each procedure is passed to the App, so that it gets "run" inside the main-loop. The problem is, the "C++ approach" does not work:
Image x("sample.png");
void visual_plot()
{
x.draw(); // Problem.
}
int main(int argc, char **argv)
{
App app(800, 600);
app.add_event_scene(Scene("Event Plot", event_plot));
app.add_visual_scene(Scene("Visual Plot", visual_plot));
app.run();
return 0;
}
Although the code runs, this happens:
And if I put the x inside the visual_plot, the image is loaded normally:
But now I have a huge performance problem, since a new Image object is being created at each main-loop (And it's not long until the whole thing freezes).
The image is not found when I put it outside the scope of the function because it must come after the initialization of the App, but since I have a typedef function pointer in Scene that takes that function as an argument, I also must give it a void function. The problem is that I can't create local / nested functions in C++ (After the initialization of the App). So, in order to avoid the problem, I've tried the obvious (Lambda expression / closure):
int main(int argc, char **argv)
{
App app(800, 600);
app.add_event_scene(Scene("Event Plot", event_plot));
Image x("sample.png");
app.add_visual_scene(Scene("Visual Plot", [&x]()->void{x.draw();}));
app.run();
return 0;
}
The problem is that the second argument of the constructor of Scene takes a function pointer:
typedef void(*plot)();
typedef map<string, plot> act;
class Scene
{
private:
string name;
plot p;
public:
Scene(string name, plot p);
~Scene() {};
string get_name();
plot get_plot();
void set_name(string value);
void set_plot(plot value);
};
And since functions cannot be passed as parameters, and get decayed to pointers, the same also applies to the lambda expression (Which is not a function), so I get the following error:
G:\Development\Game-Development\CB\Joy-Plus-Plus\main.cpp|52|error: no matching function for call to 'Scene::Scene(const char [12], main(int, char**)::__lambda0)'|
Facing such a tragedy, how can I simulate a nested function in C++11? Since simulating like this answer does not work.
OBS: I agree that it could be a design problem, but I pretty much don't see it that way. For me, C++ just don't want me to pass that bloody function as a parameter by any means (So, I ask for the help of you long C++ Wizards).
Simply put the image inside the visual_plot function and make it static:
void visual_plot()
{
static Image img("sample.png");
x.draw(); // Problem.
}
This will initialize img the first time visual_plot is called, and only then. This will solve both the performance problem and the "it must be initialized after app.run()" issue.
It is a design problem. In order to accomplish what you are trying to do you need two pieces of information: the code to execute and the data to execute it against.
A lambda isn't magic, it simply encapsulates both of these into an object, that's why it doesn't decay nicely to a single function pointer. A lambda with captures is syntactic sugar for a function object:
int x, y;
float f;
// ...
auto l = [x, &y, f] () { return static_cast<int>((x + y) * f); };
int r = l();
is saving you from writing
struct Values {
int x;
int& y;
float f;
int operator() () {
return static_cast<int>((x + y) * f);
}
Capture(int x_, int& y_, float f_) : x(x_), y(y_), f(f_) {}
};
//...
Capture c(x, y, f);
int r = c();
That's a member function call at the end there, so two pointers are involved: a pointer to the member function 'operator()' and a pointer to the instance to call it on.
int r = Capture::operator=(&c); // pseudo
Using a static or global variable you could make the address of the data known at compile time and so allow yourself to only need a function pointer.
But your design is that of a strcpy that only takes one argument or a print function that takes none: how do you know what to copy or print?
Better designs would be either to let you pass a function object to the plot functions, see how STL predicates work, which would allow both function pointers and lambdas, or use virtual functions and subclassing.
struct Scene { virtual void plot(); };
struct MyScene : public Scene {
Image x;
MyScene() : x("image") {}
void plot() override { x.draw(); }
};
The pitfall of this approach is "slicing", you need to pass Scene by reference rather than by value if you are allowing derived types:
void foo(Scene& s) {
s.plot();
}
foo(MyScene(...)); // not going to go well
I have grouped several member functions into an array. How do I access a function from the array? I am getting 'error C2064: term does not evaluate to a function taking 0 arguments.' See below.
class A
{
public:
//Constructor
A()
{
//Fill function array
ClipFunction[0] = &A::ClipTop;
ClipFunction[1] = &A::ClipBottom;
ClipFunction[2] = &A::ClipLeft;
ClipFunction[3] = &A::ClipRight;
}
//Declare array
typedef void (A::*ClipFunction_ptr) ();
ClipFunction_ptr ClipFunction[4];
//Clipping functions
void ClipTop();
void ClipBottom();
void ClipLeft();
void ClipRight();
//Start clipping process
void StartClip();
};
//Define clipping functions
void A::ClipTop() {}
void A::ClipBottom() {}
void A::ClipLeft() {}
void A::ClipRight() {}
//Define A::StartClip()
void A::StartClip()
{
//Run through all functions in the array
for (unsigned int i = 0; i < 4; i++)
{
ClipFunction[i](); //ERROR. How do I access ClipFunction[i] ???
}
}
You need to dereference the function like this:
this->(*ClipFunction[i])();
What you're missing is the this or rather the compiler is complaining that it doesn't have the first parameter (the instance of the object invoking the member function) to pass it to the function.
To the compiler the member function:
void A::ClipFunction()
{
}
translates to something like:
void ClipFunction(A* this)
{
}
Hence the error complaining that the function is not one that takes zero arguments.
I think the problem is that you need use "this" explicitly as in http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/topic/com.ibm.xlcpp8l.doc/language/ref/cplr034.htm .
So in your case, you should use
(this ->* ClipFunction[i]) ();
instead of
ClipFunction[i]();
PS
When I reply this post, I didn't see Vite Falcon's answer. Basically we are saying the same thing but I don't think his code " this->(*ClipFunction[i])()" will compile because GCC gives errors on my machine. "(this->*ClipFunction[i])()" is the correct form.
I don't think you want the scope resolution operator :: in your typedef. Instead try putting
typedef void (*ClipFunction_ptr) ();
I will like to know, how to make a function where I define a function. And then I can call the defined function. Let me try with a example.
void funcToCall() {
std::cout<<"Hello World"<<std::endl;
}
void setFuncToCall(void func) {
//Define some variable with func
}
void testFuncCall() {
//Call function that has been defined in the setFuncToCall
}
setFuncToCall(funcToCall()); //Set function to call
testFuncCall(); //Call the function that has been defined
I Hope that you understand what I am trying to do here. But I don't know how to bring It down to the right code :-)
You need a function pointer. It's easier to work with function pointers if you typedef them first.
typedef void (*FuncToCallType)();
FuncToCallType globalFunction; // a variable that points to a function
void setFuncToCall(FuncToCallType func) {
globalFunction = func;
}
void testFuncCall() {
globalFunction();
}
setFuncToCall( funcToCall ); //Set function to call,NOTE: no parentheses - just the name
testFuncCall(); //Call the function that has been defined
As other answers have suggested you can use objects like functions, too. But this requires operator overloading (even if it remains hidden from you) and is typically used with templates.
It gives more flexibility (you can set some state to the object before passing it to the function and the object's operator() can use that state) but in your case function pointers may be just as good.
What you want to use is a callback, and is has been answered her : Callback functions in c++
I would advise you to use std::tr1::function ( generalized callback )
C syntax for function pointers is a bit weird, but here we go:
// this is a global variable to hold a function pointer of type: void (*)(void)
static void (*funcp)(void);
// you can typedef it like this:
//typedef void (*func_t)(void);
// - now `func_t` is a type of a pointer to a function void -> void
// here `func` is the name of the argument of type `func_t`
void setFuncToCall(void (*func)(void)) {
// or just: void setFuncToCall(func_t func) {
//Define some variable with func
...
funcp = func;
}
void testFuncCall(void) {
//Call function that has been defined in the setFuncToCall
funcp();
}
setFuncToCall(funcToCall); // without () !
testFuncCall();
This question is similar to what I'm trying to do Calling C++ member function pointer from a struct .
However my structure contains a member function pointer that is defined in a different class then the one the structure is defined and used in. Here is some example code of how my classes, structures and function pointers are laid out.
// Alpha.h:
class Alpha{
public:
void function1(char name[], int number);
void function2(char name[], int number);
void function3(char name[], int number);
typedef void (Alpha::*My_func_ptr)(char name[], int number);
static My_func_ptr functionTable[];
};
// Alpha.cpp:
#include "Alpha.h"
Alpha::My_func_ptr Alpha::functionTable[] = {
&Alpha::function1,
&Alpha::function2,
&Alpha::function3
};
void Alpha::function1(char name[], int number)
{
//some stuff
}
void Alpha::function2(char name[], int number)
{
//some stuff
}
void Alpha::function3(char name[], int number)
{
//some stuff
}
// Beta.h:
#include "Alpha.h"
typdef struct{
char bName[10];
Alpha::My_func_ptr fptr;
}ptr_structure;
class Beta{
public:
void betafunction();
Alpha alphaobject;
ptr_structure str_array[3];
};
// Beta.cpp:
#include "Beta.h"
void betafunction()
{
str_array[0].fptr = alphaobject.functionTable[0];
str_array[1].fptr = alphaobject.functionTable[1];
str_array[2].fptr = alphaobject.functionTable[2];
(str_array[0].fptr)("name", 1); //gives error expression must have
//(pointer-to-) function type
(this->*str_array[0].fptr)("name", 1);
//error pointer-to-member selection class types are incompatible "Beta" and "Alpha"
//sample function pointer call using function table from other class,
//this syntax compiles and runs without error.
(alphaobject.*Alpha::functionTable[0]("name", 1);
}
As you can see I can call the function pointer from an array, but can't seem to figure out how to call a function pointer from inside an array of structures.
When calling a through member function pointer, you need to have an instance of the object associated with that pointer:
(alphaobject.*(str_array[0].fptr))("name", 1)
^^^^^^^^^^^
I would think:
(object.*functionTable[0])(args, ...);
(objptr->*functionTable[0])(args, ....);
IIRC, the combination of object and the .* operator is like a big unary operator. So that has lower precedence to the [0] postfix. However, it also has lower prededence than the function call postfix operator (args, ...)
Analogy:
(*foo)(); /* classic C */
Of course the * operator is not required when calling a regular function. But if you do write it, you need the parens, because *foo() means something else.
You can go to one of two solutions, depending on how readable you want the code. The unreadable version (which might even be wrong, and I won't even try to compile):
void Beta::betafunction() {
Alpha a;
(a.*(strArray[0].fptr))("name",1);
}
But I would actually try to make things a bit simpler:
void Beta::betafunction() {
Alpha a;
Alpha::My_func_ptr mptr = strArray[0].fptr;
(a.*mptr)("name",1);
}
I believe the second to be much more readable, and the compiler can optimize away mptr pretty easily, so there is no point in trying to play guru with the syntax.
Think of your basic GLUT programs. They simply run from a main method and contain callbacks like `glutMouseFunc(MouseButton) where MouseButton is the name of a method.
What I have done is I have encapsulated the main file into a class, so that MouseButton is no longer a static function but has an instance. But doing this gives me a compilation error :
Error 2 error C3867: 'StartHand::MouseButton': function call missing argument list; use '&StartHand::MouseButton' to create a pointer to member c:\users\angeleyes\documents\visual studio 2008\projects\capstone ver 4\starthand.cpp 388 IK Engine
It is not possible to provide a code sample as the class is quite huge.
I have tried using this->MouseButton but that gives the same error. Can't a pointer to an instance function be given for callback?
As the error message says, you must use &StartHand::MouseButton syntax to get a pointer to a member function (ptmf); this is simply mandated as part of the language.
When using a ptmf, the function you are calling, glutMouseFunc in this case, must also expect to get a ptmf as a callback, otherwise using your non-static MouseButton won't work. Instead, a common technique is for callbacks to work with a user-supplied void* context, which can be the instance pointer—but the library doing the callbacks must explicitly allow this parameter. It's also important to make sure you match the ABI expected by the external library (the handle_mouse function below).
Since glut doesn't allow user-supplied context, you have to use another mechanism: associate your objects with glut's current window. It does provide a way to get the "current window", however, and I've used this to associate a void* with the window. Then you simply need to create a trampoline to do the type conversion and call the method.
Machinery:
#include <map>
int glutGetWindow() { return 0; } // make this example compile and run ##E##
typedef std::pair<void*, void (*)(void*,int,int,int,int)> MouseCallback;
typedef std::map<int, MouseCallback> MouseCallbacks;
MouseCallbacks mouse_callbacks;
extern "C" void handle_mouse(int button, int state, int x, int y) {
MouseCallbacks::iterator i = mouse_callbacks.find(glutGetWindow());
if (i != mouse_callbacks.end()) { // should always be true, but possibly not
// if deregistering and events arrive
i->second.second(i->second.first, button, state, x, y);
}
}
void set_mousefunc(
MouseCallback::first_type obj,
MouseCallback::second_type f
) {
assert(obj); // preconditions
assert(f);
mouse_callbacks[glutGetWindow()] = MouseCallback(obj, f);
//glutMouseFunc(handle_mouse); // uncomment in non-example ##E##
handle_mouse(0, 0, 0, 0); // pretend it's triggered immediately ##E##
}
void unset_mousefunc() {
MouseCallbacks::iterator i = mouse_callbacks.find(glutGetWindow());
if (i != mouse_callbacks.end()) {
mouse_callbacks.erase(i);
//glutMouseFunc(0); // uncomment in non-example ##E##
}
}
Example:
#include <iostream>
struct Example {
void MouseButton(int button, int state, int x, int y) {
std::cout << "callback\n";
}
static void MouseButtonCallback(
void* self, int button, int state, int x, int y
) {
static_cast<Example*>(self)->MouseButton(button, state, x, y);
}
};
int main() {
Example obj;
set_mousefunc(&obj, &Example::MouseButtonCallback);
return 0;
}
Notice that you don't call glutMouseFunc directly anymore; it is managed as part of [un]set_mousefunc.
Just in case it isn't clear: I've rewritten this answer so it should work for you and so that it avoids the C/C++ linkage issue being debated. It will compile and run as-is (without glut), and it should work with glut with only minor modification: comment or uncomment the 4 lines marked ##E##.
No, a pointer to an instance function can not be given to a callback function expecting a function pointer of a certain signature. Their signatures are different. It won't compile.
Generally such APIs allow you to pass in a void* as a "context" parameter. You pass in your object there, and write a wrapper function which takes the context as the callback. The wrapper casts it back to whatever class you were using, and calls the appropriate member function.
You can't replace a static callback with an instance one. When the caller calls your callback, on what instance whoul it call? In other words, how does the caller pass in the formal 'this' argument?
The solution is to have a static callback stub and pass the instance as argument, which implies the callee must accept an arbitrary pvoid that will pass back when invoking the callback. In the stub, you can then call the non-static method:
class C {
void f() {...}
static void F(void* p) {
C* pC = (C*)p;
pC->f();
}
}
C* pC = ...;
someComponent.setCallback(&C::F, pC);
Contrary to what everyone seems to be saying, you most definitely CAN use a non-static member function as a callback method. It requires special syntax designed specifically for getting pointers to non-static members, and special syntax to call that function on a specific instance of a class. See here for a discussion of the needed syntax.
Here is sample code that illustrates how this works:
#include <cstdlib>
#include <string>
#include <iostream>
#include <vector>
#include <sstream>
#include <algorithm>
using namespace std;
class Operational
{
public:
Operational(int value) : value_(value) {};
string FormatValue() const ;
private:
int value_;
};
string Operational::FormatValue() const
{
stringstream ss;
ss << "My value is " << value_;
return ss.str();
}
typedef string(Operational::*FormatFn)() const; // note the funky syntax
Operational make_oper(int val)
{
return Operational(val);
}
int main()
{
// build the list of objects with the instance callbacks we want to call
Operational ops[] = {1, 2, 3, 5, 8, 13};
size_t numOps = sizeof(ops)/sizeof(ops[0]);
// now call the instance callbacks
for( size_t i = 0; i < numOps; ++i )
{
// get the function pointer
FormatFn fn = &Operational::FormatValue;
// get a pointer to the instance
Operational* op = &ops[i];
// call the callback on the instance
string retval = (op->*fn)();
// display the output
cout << "The object # " << hex << (void*)op << " said: '" << retval << "'" << endl;
}
return 0;
}
The output of this program when I ran it on my machine was:
The object # 0017F938 said: 'My value is 1'
The object # 0017F93C said: 'My value is 2'
The object # 0017F940 said: 'My value is 3'
The object # 0017F944 said: 'My value is 5'
The object # 0017F948 said: 'My value is 8'
The object # 0017F94C said: 'My value is 13'
You cannot use a non-static member function in this case.
Basically the type of the argument expected by glutMouseFunc is
void (*)(int, int, int, int)
while the type of your non-static member function is
void (StartHand::*)(int, int, int, int)
First problem is that types don't really match.
Second, in order to be able to call that method, the callback would have to know which object ( i.e. "this" pointer ) your method belongs to ( that's pretty much why the types are different in the first place ).
And third, I think you're using the wrong syntax to retrieve the method's pointer. The right syntax should be: &StartHand::MouseButton.
So, you have to either make that method static or use some other static method that would know which StartHand pointer to use to call MouseButton.
The following works in c++ to define a c callback function, useful for example when using glut (glutDisplayFunc, glutKeyboardFunc, glutMouseFunc ...) when you only need a single instance of this class :
MyClass * ptr_global_instance = NULL;
extern "C" void mouse_buttons_callback(int button, int state, int x, int y) {
// c function call which calls your c++ class method
ptr_global_instance->mouse_buttons_cb(button, state, x, y);
}
void MyClass::mouse_buttons_cb(int button, int state, int x, int y) {
// this is actual body of callback - ie. if (button == GLUT_LEFT_BUTTON) ...
// implemented as a c++ method
}
void MyClass::setup_glut(int argc, char** argv) { // largely boilerplate glut setup
glutInit(&argc, argv);
// ... the usual suspects go here like glutInitWindowSize(900, 800); ...
setupMouseButtonCallback(); // <-- custom linkage of c++ to cb
// ... other glut setup calls here
}
void MyClass::setupMouseButtonCallback() {
// c++ method which registers c function callback
::ptr_global_instance = this;
::glutMouseFunc(::mouse_buttons_callback);
}
In your MyClass header we add :
void mouse_buttons_cb(int button, int state, int x, int y);
void setupMouseButtonCallback();
This also works using identical logic flows to setup your glut
call to glutDisplayFunc(display)