It looks like you're new here. If you want to get involved, click one of these buttons!
orxSTATUS orxFASTCALL EventHandler(const orxEVENT *_pstEvent) {
//stuff
}
orxSTATUS orxFASTCALL Init(){
orxEvent_AddHandler(orxEVENT_TYPE_ANIM, EventHandler);
}
#ifndef MYSTUFF_H
#define MYSTUFF_H
class MyStuff
{
public:
MyStuff();
~MyStuff();
orxSTATUS orxFASTCALL EventHandler(const orxEVENT *_pstEvent);
}
#endif // MYSTUFF_H
void MyStuff::MyStuff()
{
orxEvent_AddHandler(orxEVENT_TYPE_ANIM, EventHandler); <------ error
}
orxSTATUS orxFASTCALL MyStuff::EventHandler(const orxEVENT *_pstEvent) {
//stuff
}
I'm probably missing something very simple. I've fixed up all other aspects, but adding events in the code files is really dogging me.C:/Work/project/mystuff.cpp:45:54: error: cannot convert 'MyStuff::EventHandler' from type 'orxSTATUS (MyStuff:: )(const orxEVENT*) {aka __orxSTATUS_t (MyStuff:: )(const __orxEVENT_t*)}' to type 'orxEVENT_HANDLER {aka __orxSTATUS_t (__attribute__((__fastcall__)) *)(const __orxEVENT_t*)}'
Comments
I think that orxEvent_AddHandler() is missing the "context" paramere where you could pass the this pointer to be able to use as member function (with some minor wrapping code, either using lambda or helper static function).
Please excuse my limited understanding of C++.
What confuses me is: why is it valid for orxEvent_AddHandler() to accept EventHandler in the first example, yet in the second example, where the class and definitions are separate, it is somehow different?
Is EventHandler in a different form between the two examples?
In short, you cannot use non-static member function as event handlers, now. If you change the function to static you could use it as the event handler, but will not be tied to any instance (the behaviour id the same as free function but because it is part of the class, it could access static class members).
edit: To be it more clear, to be able to call member function, you need some class instance. orxEvent_AddHandler() accept only function pointer you could pass there only free function pointer or static member function pointer. If the function has addition context parameter, for instance void *, you could then write something like this
I will definitely need to tie a particular eventhander to a specific class.
I'll experiment with your code snippets and see how I go.
Thanks again.
I really think that orxEvent_AddHandler() should have additional parameter as for instance orxClock_Register() has. Otherwise I don't think it will be possible to register the event handler per instance basis.
My current need is that I eventually want to have four tables in the game that the user can select to play. Most of the logic would be shared between all the tables, functions like:
void LaunchBall();
void DestroyBall();
...
etc etc.
Currently it seems like the best approach would be to move everything into a base class and each pinball table class inherit from the base class and just override the functions that are different. (or add ones that are new)
But the event methods can't be used in this way.
Perhaps the events don't need to be part of the classes. Perhaps the derived class can pass the event functions outside to the event handlers as part of it's setup.
I am happy to try and work with a singleton approach as my current way may not be architecturally the best. I only understand c# singletons so I'll read up.
The above will add an extra layer of function indirection for your events, but I doubt that it will affect performance.
If you have multiple tables at the same time, you can switch the singleton into a container (a linked list for instance,) handle insertion/removal of tables in the base class, and instead of dispatching the event handler on a single instance, you would iterate the container and dispatch on every instance.
You are correct that there is only one instance of a table at a time. So I'm really using inheritance for re-use, not for creating many instances of the class at once. A singleton pattern sounds ideal.
This is a rather straightforward change and the context will be part of the event sent (so no need for a new signature for handlers).
That being said, Trigve, keep an eye on the performances as all the handlers will be called for every event, resulting in many more calls than if you were doing the dispatch yourself.
Sausage: in your case, as you'll only have a single instance of the handler there won't be any additional cost, so you can either go with the context or the singleton approach, they're equivalent in your case.
Thanks iarwain for the response and change.
I'm fully aware of the performance problems that could happens. But even when using the dispatch mechanism, you should somehow query if the event is targeted for the given instance or not. The question is, what will be faster (the dispatch mechanism could be theoretically faster, because if you find the first instance the event belongs to, you are done. In the other cases, all the events handler should run even if they aren't doing anything).
Even using the dispatch mechanism I think this is good change (the context parameter), because I don't need to pollute my class with some static instances.
Just my 2 cents. Would love to hear other opinions on this matter.
In Sausage's case, if he were to have more than a table at once, he could store in his objects the ID of the table so that when he handles an object event, he could access the right table directly.
I don't mind the extra context parameter, it doesn't really have any perf impact on the system and was easy to add, I was just curious to know in which circumstances people would use it. With orx+Scroll I haven't had those situations yet: I could always somehow infer the context from the content of the event itself.
Bottom line is, it is all now working so sweet and I can start back to the business of the game.
Thank you, gentlemen. Very much appreciated.
main.cpp
PinballBase.h
PinballBase.h
DerivedTable.h
DerivedTable.cpp