So here's the situation: I'm using C++, SDL and GLConsole in conjunction. I have a class, SDLGame, which has the Init(), Loop(), Render() etc - essentially, it holds the logic for my game class.
GLConsole is a nice library so far - it lets me define CVars and such, even inside my SDL class. However, when defining commands, I have to specify a ConsoleFunc, which is typedef'd as
typedef bool (*ConsoleFunc)( std::vector<std::string> *args);
Simple enough. However, like I said, my functions are all in my class, and I know I can't pass pointer-to-class-functions as pointer-to-function arguments. I can't define static functions or make functions outside my class because some of these ConsoleFuncs must access class data members to be useful. I'd like to keep it OOP, since - well, OOP is nice.
Well, I actually have this problem "solved" - but it's extremely ugly. I just have an instance of SDLGame declared as an extern variable, and use that in my ConsoleFuncs/main class.
So, the question is: Is there a way to do this that isn't stupid and dumb like the way I am doing it? (Alternatively: is there a console library like GLConsole that supports SDL and can do what I'm describing?)
If the only interface you have is that function pointer, then you're screwed.
A member function needs a this pointer to be called, and if you have no way of passing that, you're out of luck (I guess the std::vector<std::string>* args pointer is what you get passed from the library).
In other words, even though that library uses C++ containers, it's not a good C++ library, because it relies on free functions for callbacks. A good C++ library would use boost::function or something similar, or would at the very least let you pass a void* user_data pointer that gets passed through to your callback. If you had that, you could pass the this pointer of your class, cast it back inside the callback, and call the appropriate member function.
Related
I'm currently learning game development with c++ in Unreal Engine and I came across the function that takes a function pointer as an input:
InputHandle->BindAction("Grab",IE_Pressed, this, &UGrabber::Grab);
From basic C++ I know that in passing a function pointer as an attribute (UGrabber::Grab) - & is optional, however UEngine complains with the following error code if I omit the &:
error C3867: 'UGrabber::Grab': non-standard syntax; use '&' to create a pointer to member
Could someone explain why?
BindAction function declaration looks like this:
FInputActionBinding& BindAction( const FName ActionName, const EInputEvent KeyEvent, UserClass* Object, typename FInputActionHandlerSignature::TUObjectMethodDelegate< UserClass >::FMethodPtr Func )
The BindAction function makes use of a Dynamic Multicast Delegate.
They are one of Unreal's ways of having callback functions. In this case, they rely not just on calling a function, but calling a specific object's function. This is why you need to bass the third parameter (in this example, the parameter is this).
What it's saying is, when the input action is IE_Pressed, call the UGrabber function Grab on object this (this has to be a UGrabber instance of course). This is why it's a pointer to the method. It actually utilizes Unreal's reflection system to find the method on the object. So the this object needs to be UObject, otherwise you can't call a funciton on an object by name in C++.
For more info on this, search for "unreal delegates" and "unreal reflection" in your search engine of choice. Using them is quite easy, and it's not necessary to understand the reflection system to reliably use them. Just don't forget to bind and unbind at the appropriate times.
p.s. You can get quite in depth in this subject of callbacks you want. There are other delegate types that don't rely on reflection, for example non-dynamic delegates, that can bind to lambda functions, and or a more familiar if you're coming from a pure C++ background, where commonly a void* opaque is used, expected to be cast to the needed class pointer.
I have two classes, ClassWorking and TemplateClass, they are not related in any way.
Is there a way to say, I want the function TemplateGenerate() from my TemplateClass now to behave like the function generate() from my class ClassWorking.
Like a (this function does not exist) SetFunctionBehavior(&templateClassRef->templateGenerate, &classWorkingRef->generate)
I know I can use function pointer to make TemplateClass receive a pointer and call it in the class, but that not what I want.
It's more something like a LD_Preload, to replace the inner of function without having to re-write it and without inherit from a class who has it.
to be a little more explicit let's see it more like a node construction for class
TemplateClass can have multiple functions but not with the same behaviour
- TemplateClass
- TemplateGenerate() {will do this}
- TemplateGenerate() {will do that}
- TemplateGenerate() {will do like that}
and when I declare my class pointer templateClassRef->TemplateGenerate = TemplateGenerate() {will do that}
but not with a lambda :)
The point is to have something really generic without having to re-create a class for each need, for example I could have a class:
TemplateGenerate
- function A {A1 Behavior} Functiun B {B1 Behavoir} Functiun C {C1 Behavior}
{A2 Behavior} {B2 Behavoir} {C2 Behavior}
{A3 Behavior} {B3 Behavoir} {C3 Behavior}
And when I declare my function I say I take A1,B2,C3 or A1,B1,C2
The method ClassWorking::generate is a function that takes a ClassWorking and does stuff.
A function that has the same behaviour also takes a ClassWorking. That is part of what the function does.
As TemplateClass is unrelated to ClassWorking, a method TemplateClass::templateGenerate that "behaves alike" ClassWorking::generate cannot succeed; you don't have a ClassWorking, so one of the prequisites of ClassWorking::generate isn't being fullfilled.
Now, it might be the case that the implementation of ClassWorking::generate doesn't actually need an instance of ClassWorking. It might need something else.
But for the compiler to know this, you have to change the method from being a method of ClassWorking to being something else. For example, you could write a free function generate that takes an argument what you actually need, and have ClassWorking::generate call that free function.
Then calling the free function generate from a stub method TemplateClass::templateGenerate becomes trivial.
C++ does not support "do what I mean" or "read my mind". You actually have to tell the compiler what you want to happen. And types matter in C++, so you cannot wire up a method on one class to another class without also telling C++ how the types relate.
There are languages where types are looser and you actually can grab a method off one class and glue it onto another. These are generally interpreted languages with much heavier runtime object models than C++; members in this language are implemented as property bags of named values, values are actually variants at runtime, etc.
You can implement that kind of object in C++, but it isn't a "native" C++ object, and you'll have to write a pile of glue code (some of which could be hidden by metaprogramming). That is far from a beginner task, and usually a bad idea; if you need the flexibility of scripting languages, just use a scripting language.
One way is to use composition. Define an interface
struct Interface
{
virtual void/*maybe*/ templateGenerate(/*maybe*/) /*const?*/ = 0;
};
Then implement
struct ClassWorkingImpl : Interface, ClassWorking
{
// ToDo - delegate all the constructors
// ToDo - implement templateGenerate using the method in ClassWorking
};
and similarly for TemplateClass.
Then you instantiate ClassWorkingImpl &c. rather than ClassWorking. And you can call the interface method templateGenerate on either.
So here's the situation: I'm using C++, SDL and GLConsole in conjunction. I have a class, SDLGame, which has the Init(), Loop(), Render() etc - essentially, it holds the logic for my game class.
GLConsole is a nice library so far - it lets me define CVars and such, even inside my SDL class. However, when defining commands, I have to specify a ConsoleFunc, which is typedef'd as
typedef bool (*ConsoleFunc)( std::vector<std::string> *args);
Simple enough. However, like I said, my functions are all in my class, and I know I can't pass pointer-to-class-functions as pointer-to-function arguments. I can't define static functions or make functions outside my class because some of these ConsoleFuncs must access class data members to be useful. I'd like to keep it OOP, since - well, OOP is nice.
Well, I actually have this problem "solved" - but it's extremely ugly. I just have an instance of SDLGame declared as an extern variable, and use that in my ConsoleFuncs/main class.
So, the question is: Is there a way to do this that isn't stupid and dumb like the way I am doing it? (Alternatively: is there a console library like GLConsole that supports SDL and can do what I'm describing?)
If the only interface you have is that function pointer, then you're screwed.
A member function needs a this pointer to be called, and if you have no way of passing that, you're out of luck (I guess the std::vector<std::string>* args pointer is what you get passed from the library).
In other words, even though that library uses C++ containers, it's not a good C++ library, because it relies on free functions for callbacks. A good C++ library would use boost::function or something similar, or would at the very least let you pass a void* user_data pointer that gets passed through to your callback. If you had that, you could pass the this pointer of your class, cast it back inside the callback, and call the appropriate member function.
I've started using OpenGL a while ago, using GLUT. You can't pass member functions to GLUT functions. (or pointers to members for that matter, though I did not explore that option really far).
I was wondering if there is a "decent" way, or what is the "most decent" way to solve this? I know you can use static member functions, but isn't there a better way?
I know there are other libraries, like SFML that are written in C++ and provide a C++ class-based interface, but I was wondering what the possibilities are concerning GLUT (freeglut to be exact).
First, GLUT is not for serious application work. It's for simple graphics demos. And for that purpose, it is fine. If you find yourself trying to do serious work in GLUT, you will find yourself spending lots of time working around its limitations. This limitation is only one of many that you will eventually encounter. GLFW, while still having this limitation (though the next version will not), is generally superior for serious application work.
Second, the "most decent" way to solve this depends on what you're doing. If you only have one window, then the correct solution is just a simple static function, which can global pointers (or functions that return global pointers) to whatever class you're interested in.
If you have multiple windows, then what you need is a global std::map that maps from GLUT's window identifiers to pointers to some object. Then you can get which window a particular function was called from and use the map to forward that call to the particular object that represents that window.
Passing member functions to glut, or any other library, is easy enough. GLUT is looking for a function pointer.
Let Controller be a class with a member function OnKeyPress that we want to send into glutKeyboardFunc. You might first be tempted to try something like
glutKeyboardFunc(&Controller::OnKeyPress);
Here, we are passing a function pointer, however this is incorrect, since you want to send the member function of that class object. In C++11 you can use the new std::bind, or if you are on an older compiler, I would recommend boost::bind. Either way the syntax is around the same.
using namespace std::placeholders; // for the _1, _2 placeholders
glutKeyboardFunc(std::bind(&Controller::OnKeyPress, &GLInput, _1, _2, _3));
From the documentation it looks like glutKeyboardFunc requires 3 parameters. First we fix the first argument memory address of your object, since its a member function, and then supply 3 placeholders.
For those new to std::bind, it feels odd, but for anyone who has done object oriented code in C, its obvious. The function is really just a C function, and needs the "this" pointer to the class. The bind would not be necessary if the callback was a simple function.
What is mean by delegates in c++, does sort function in c/c++ which takes a compare function/functor as last parameter is a form of delegate?
"delegate" is not really a part of the C++ terminology. In C# it's something like a glorified function pointer which can store the address of an object as well to invoke member functions. You can certainly write something like this in C++ as a small library feature. Or even more generic: Combine boost::bind<> with boost::function<>.
In C++ we use the term "function object". A function object is anything (including function pointers) that is "callable" via the function call operator().
std::sort takes a "predicate" which is a special function object that doesn't modify its arguments and returns a boolean value.
Callback functions in C++ can be (loosely) referred as a form of delegates ( though delegate term is not used for this). The callback functions use Pointers to Functions to pass them as parameters to other functions.
But delegates in C# is more advanced compared to callback functions in C++.
To delegate work means to share the work load with others. In real life, if you were to delegate your task, ie if you are a manager, you would be sharing your work expecting others to complete a task without you having to know how.
The concept is the same in C++ and any other languages having the capability of delegates. In C you could see this as a delegate:
int calculate(int (*func)(int c), int a, int b)
Because you are expected to send a pointer, to another function which will compute some work for you. I recently wrote a blog post on function pointers in Python and C, check it out, you might find it helpfull. This might not be the "traditional" way to delegate work in C or C++, but then again, the termonoligy says i am a bit right.
Delegation is mostly used as a way to pass functions to functionality embedded in a class (pimpl, aggregation, private inheritance). They are mainly (inlined) functions of one line, calling functions of member-classes. As far as I know, it has nothing to do with C#'s delegates.
In this sense, a function-pointer as used in qsort is not a delegate, but a callback in which framework modules can be extended by user-software as in the Hollywood principle.
Delegate: An object that acts like a multi-function pointer with a subscription system. It really simplifies the use of static or 'object' member function pointers for callback notifications and event handling.
This link explains Delegates in a lucid manner or you may also refer to the MSDN link.