Skip to main content
GameDev.net gamedev.net
🔒 Locked

C++ Callback Reference

Started by CyberSlag5k Feb 16, 2009 at 11:54 AM 15 replies 2.3k views
Original Post
CyberSlag5k
CyberSlag5k
I've got an callback method for an event handler:

void Keys::KeyDown_Escape(const Event* senderEvent, void* data)
{
   bool* exitFlag = (bool*)data;

   *exitFlag = true;
}


And I'm passing it a reference to a boolean (&exitFlag), but for some reason, that boolean is not getting set to true after the callback method returns. I'm a little off my C++ game, so I'm not quite sure what I'm doing wrong. I've also tried using references, instead of pointers (bool& exitFlag = (bool&)data), but that didn't work, either. I'm not even sure that the correct reference is getting passed in, as the value seems to be set to true before the assignment call. I'm working with the Panda3D engine, so here's what my event handler call looks like:

framework.define_key("escape", "Closes the framework", Keys::KeyDown_Escape, &exitFlag);


exitFlag is just a global variable, initliazed to false and never set anywhere but the callback method, which makes me suspicious that I'm not passing in the correct reference, as it's coming in as true on the callback. Might anyone see what I'm doing wrong?
Without order nothing can exist - without chaos nothing can evolve.
RIZAX
RIZAX
Ive never used Panda, but from what your posting, arent you redefining exitFlag within the callback, forcing local scope which means your global is never getting set to anything?
soconne
soconne
You should probably post your code for define_key since that is what is making the final call.
Author Freeworld3Dhttp://www.freeworld3d.org
loufoque
loufoque
This looks correct.
_moagstar_
_moagstar_
How are you defining the global? I could see how this could happen if you have something like this :

// header.hstatic bool exitFlag(false);


// one.cppframework.define_key("escape", "Closes the framework", Keys::KeyDown_Escape, &exitFlag);


// two.cppif (exitFlag){    // do something}


Then exitFlag is a static variable that exists in every translation unit. So the exitFlag in one.cpp is a different variable to the exitFlag in two.cpp.

I'm not sure if this is the problem, but if it is then you have three choices

- Declare the variable as external (use extern keyword in .h and define it in only one .cpp file)
- Make the global a static variable within a function and provide get / set for it.
- Don't use a global variable

Personally, I would go with the third option.
CyberSlag5k
CyberSlag5k
I'm defining it just like this:

bool exitFlag = false;

And it doesn't need to be a global variable. I'll make it local when I get home. Could that be causing the problem? If so, how?
Without order nothing can exist - without chaos nothing can evolve.
_moagstar_
_moagstar_
Perhaps not then, I would expect that if you were declaring it like that in a header file without making it static, then you would have some linker errors when you include the header in two seperate .cpp files.

How is the code structured? Is it all in one .cpp file or is it split over multiple files? Where are you declaring your global variables, in the headers or in the source files?

I don't think making it a local variable will help, because you will be then giving that function the address of a local variable, which is about to go out of scope.
CyberSlag5k
CyberSlag5k
Original post by _moagstar_
Quote:

How is the code structured? Is it all in one .cpp file or is it split over multiple files? Where are you declaring your global variables, in the headers or in the source files?


The variable in question, and the framework variable, are declared at the top of main.cpp. The call to define_key (a Panda function) is in an initialization function in main.cpp. The callback, KeyDown_Escape, is declared in Keys.h and defined in keys.cpp (files I created specifically to handle these types of events). Is that sufficient? I don't have the code in front of me, but it's pretty bare bones at this point, so I could probably answer some more questions.

Quote:

I don't think making it a local variable will help, because you will be then giving that function the address of a local variable, which is about to go out of scope.


Good point.

Without order nothing can exist - without chaos nothing can evolve.
Deception666
Deception666
Post your Keys.cpp and Keys.h. More visual clues are always better than chitchat.

Have you tried setting a break point or pumping text to a prompt to verify that the code is being executed?
_moagstar_
_moagstar_
From what you describe I can't see why it wouldn't be working. Perhaps you could post the code when you have it available.
CyberSlag5k
CyberSlag5k
Will do. Thanks.
Without order nothing can exist - without chaos nothing can evolve.
CyberSlag5k
CyberSlag5k
This is everything. Thanks for taking a look.

I have to run in release mode, so I'm turning compiler optimization off in two of the files, to help the debugger be a little more accurate. That's what the #pragam optimizes are for.
Without order nothing can exist - without chaos nothing can evolve.
CyberSlag5k
CyberSlag5k
Hmm... using standard error for output, I was able to verify that this works:

	bool* exitFlag = (bool*)data;	*exitFlag = true;


The code with the references in it had data at some value 148 (according to cerr) before the assignment, and a value of 1 afterwards. That suggests that there was a problem in the reference code. Can anyone see what it was?
Without order nothing can exist - without chaos nothing can evolve.
_moagstar_
_moagstar_
Ah ok I see what is happening now. You are casting a pointer to a reference, if you change bool exitFlag = (bool&)data; to int exitFlag = (int&)data; you can see precisely what is happening when you try and do this.

You are asking the compiler for a integer reference to data, if you use (int&) you should see that the integer is the same as the address stored in data*, when you step over the exitFlag = true line you should see the address stored in data change to 0x00000001.

If you use static_cast for situations like this the compiler will tell you that you have done something wrong.

This should work fine :

bool* exitFlag = static_cast<bool*>(data);*exitFlag = true;

CyberSlag5k
CyberSlag5k
Ah, I see now that I posted the pointer version in this post. I was going back and forth between that and the reference version, as neither seem to be working.

So what was getting stored in the boolean reference? The address of the data pointer? I can see how that would be bad.

My code is working as is, is there still a reason to use static_cast? Good practice?

Thank you for your help.
Without order nothing can exist - without chaos nothing can evolve.
_moagstar_
_moagstar_
You were getting a reference to the pointer, not to the data that the pointer was pointing to.

(bool&) is a c style cast, the c++ style casts are much more useful, here is a fairly good run down of the different flavours and what they do.

If you had used static_cast in this particular case the compiler would have used the information available at compile time to determine that the cast was illegal.
CyberSlag5k
CyberSlag5k
Thanks. I remember reading about the different C++ casts in Effective (or More Effective) C++, but I didn't really remember the specifics.
Without order nothing can exist - without chaos nothing can evolve.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.