How does luabind implicitly cast objects? - c++

Without going into too many irrelevant details about a large multi-library project I'm working on I'd like to ask a question about a specific event that occurred in it. I'm using Luabind to have my C++ code interface with my Lua code and I have a class structure with inheritance like so:
GuiWidget
GuiButton : GuiWidget
I've registered both of these classes with Lua via Luabind. Then I do the following, where widget is a pointer to an instance of the GuiWidget class:
lua_newtable(luaState);
luabind::object(luaState, widget).push(luaState);
lua_setfield(luaState, 2, "widget");
lua_setglobal(luaState, "event");
//This line connects to some other code I wrote that just executes a file and handles errors.
luaMachine->doFile(widget->getUserString("eventMouseButtonClick"));
lua_pushnil(luaState);
lua_setglobal(luaState, "event");
Now this same code snippet can handle anything from buttons to scroll bars and even entire windows. So later on in the lua code I call this line of code for when a check box button is clicked:
event.widget:setSelected(not event.widget:getSelected())
This works. Even though the pointer pushed through is a GuiWidget pointer the lua code somehow knows to use functionality unique to GuiButton class for this particular instance. How does it do that? How does it take a widget pointer and automatically know that particular widget is a button? I didn't believe it was possible so it took me a while to arrive at that solution but I figured I'd take a shot in the dark and it worked somehow.

It has been a long time since you asked but i may have an answer for this...
luabind generates internal unique ID for every type you register when you start your executable (+ wrappers etc...)
There is global "map" in LUA_REGISTRYINDEX called __luabind_class_id_map translating typeid to this previously assigned internal unique ID
When you return pointer (GuiWidget) luabind asks for typeid of returned pointer by dereferencing it -> typeid(ptr). This surprisingly returns type_info of GuiButton not GuiWidget (although GuiWidget ptr = new GuiButton();)
Then luabind translates typeid of GuiButton into internal ID and finds class_rep for that in another LUA_REGISTRYINDEX table (__luabind_class_map). class_rep holds how object should be stored on Lua side and other info related to registered c++ class.
Last interesting info for making this to work is, that all pointers on Lua side are stored like so: dynamic_cast(ptr) that later allows for auto casting from that to other classes validated using previous method and inheritance info in class_rep
That is roughly how this implicit casting can be done / is done in luabind library.

Related

Monitoring C pointer by using KVO

I am trying to create a function in Objective-C for monitoring a pointer declared on my C/C++ side of code by using KVO. Is there a way to do this?
To elaborate. I have a C object pointer. I pass that pointer as void* through my bridge function down to Objective-C side of the code.
Is it possible to use the pass-down void* to set up KVO and notify via:
-(void)observeValueForKeyPath:(NSString *) keyPath of Object:...
when the C object pointer is modified by C side of code?
KVO, with its ability to just observe a property and automatically get notifications every time it changes, seems like magic, but really all it is is Apple automatically changing your property's setter from this:
- (void)setFoo:(Foo *)newFoo {
self.foo = newFoo;
}
into this:
- (void)setFoo:(Foo *)newFoo {
[self willChangeValueForKey:#"foo"];
self.foo = newFoo;
[self didChangeValueForKey:#"foo"];
}
The will and didChangeValueForKey: methods are what cause the KVO system to check for observers for the property, and notify them if there are any. The automatic substitution of the setter is done by taking advantage of the extremely dynamic nature of Objective-C, which makes it relatively simple to patch methods and alter them at runtime (this is, incidentally, why the dynamic keyword is needed to implement KVO properties in Swift). Of course, these dynamic features do not exist in C or C++.
What you will need to do, then, is to have your C code define two callbacks; one which the C code will call before changing the value, and another which it will call afterwards. Once you've got this set up, have the Objective-C side register these callbacks somewhere in your setup process, and have the callbacks call the willChangeValueForKey: and didChangeValueForKey: methods. Once you've done this, you should be able to observe the property using the normal KVO methods.

Creating a "Publisher->Dispatcher->Subscriber" pattern event system?

Edit: TL;DR
I guess my main problem is I don't know how to store a list of functions that all take one argument, where the argument type is different between each function, but always extends from EventBase, for calling later.
i.e: EventChild extends from EventBase. A function with the signature
<void (EventChild&)>
will not fit into a variable of type
std::function<void(EventBase&)>
How do I store functions like this, knowing that a user shouldn't have to modify the class where they are stored each time they create a new event extending from our EventBase class?
Note: I had previously been told I could use a dynamic_cast to accomplish this. I have been trying to do exactly that, but it hasn't been working. I imagine for that to work I would have to use pointers somehow, but I am new enough to C++ that I'm not sure how to do it. Maybe that should be the starting point?
One of the problems with dynamic casting pointers I have been having is 'I can convert a pointer of type:
(Subbscriber*)(getDemoEvent(EventDemo&)
to type:
void(EventBase&)
or something along those lines. (not at my computer right now to try it)
This is obviously a problem limited to member functions, I assume.
I recently posted a question on here with the intention of solving an issue for a C++ Event system based on a "Publisher->Dispatcher->Subscriber" pattern. I don't know the exact name of this pattern, but I hear that it is a variant on the Observer pattern with an added "middle-man."
I have been trying to get this system to work for a while now and I am completely stuck. It was suggested in the comments of the previous question that for what I was trying to accomplish, my program layout is incorrect. This is very likely the case since I had been researching other event systems that were close to what I am after trying to modify them for use they were unintended for. So I figured I would describe what I am after, and ask the more general question of "How would you go about structuring and creating this?"
So here is my general idea of how the system should be laid out and how it should operate in a basic example:
Starting with the idea of 5 different files (plus headers and maybe some subclasses):
main.cpp
dispatcher.cpp
publisher.cpp
subscriber.cpp
eventbase.cpp
publishers and subscribers could be anything, and they only serve as an example here.
The first order of business would be to create an instance of our Dispatcher class.
Following that, we create instances of our publisher/subscriber classes. These 2 classes could be a part of the same file, different files, multiples of each, or not event be classes at all but simply free functions. For the sake of simplicity and testing, they are 2 separate classes that know nothing about each other.
When these 2 classes are created, they should be passed a reference or pointer to our dispatcher instance.
This is easy enough. Now let's get to how you should use the system.
A user of the system should be able to create a class that inherits from our EventBase class. Ideally, there should be no requirement on variables or functions to override from the base class.
Let's say we have created a new event class called EventDemo, with a public const char* demoString = "I am a Demo Event";.
From our subscriber class, we should be able to tell our dispatcher that we want to listen for and receive some events. The syntax for doing so should be as simple as possible.
Lets create a member function in our subscriber that looks like this:
void Subscriber::getDemoEvent(const EventDemo &ev) {
std::cout << ev.demoString;
}
Now we need a way to bind that member function to our dispatcher. We should probably do that in our constructor. Let's say that the reference to our dispatcher that we passed to our subscriber when we created it is just called 'dispatcher'.
The syntax for subscribing to an event should look something like this:
dispatcher->subscribe("EventToSubTo", &getDemoEvent);
Now since we are in a class trying to pass a member function, this probably isn't possible, but it would work for free functions.
For member functions we will probably need and override that looks like this:
dispatcher->subscribe("EventToSubTo", &Subscriber::getDemoEvent, this);
We use 'this' since we are inside the subscribers constructor. Otherwise, we could use a reference to our subscriber.
Notice that I am simply using a string (or const char* in c++ terms) as my "Event Key". This is on purpose, so that you could use the same event "type" for multiple events. I.E: EventDemo() can be sent to keys "Event1" and "Event2".
Now we need to send an event. This can be done anywhere we have a reference to our dispatcher. In this case, somewhere in our publisher class.
The syntax should look something like this to send our EventDemo:
dispatcher->emit("EventToSubTo", EventDemo());
Super simple. It's worth noting that we should be able to assign data to our event through it's constructor, or even template the event. Both of these cases are only valid if the event created by the user supports it.
In this case, the above code would look something like this:
dispatcher->emit("EventToSubTo", EventDemo(42));
or
dispatcher->emit("EventToSubTo", EventDemo<float>(3.14159f));
It would be up to the user to create a member function to retrieve the data.
OK, so, all of that should seem pretty simple, and in fact, it is, except for one small gotcha. There are already systems out there that store functions in a map with a type of .
And therein lies the problem...
We can store our listener functions, as long as they accept a type of EventBase as their argument. We would then have to type cast that argument to the type of event we are after. That's not overly difficult to do, but that's not really the point. The point is can it be better.
Another solution that was brought up before was the idea of having a separate map, or vector, for each type of event. That's not bad either, but would require the user to either modify the dispatcher class (which would be hard to do when this is a library), or somehow tell the dispatcher to "create this set of maps" at compile time. That would also make event templating a nightmare.
So, the overly generalized question: How do we do that?
That was probably a very long winded explanation for something seemingly simple, but maybe someone will come along not not know about it.
I am very interested to hear thoughts on this. The core idea is that I don't want the 2 communicators (publisher and subscriber) to have to know anything about each other (no pointers or references), but still be able to pass arbitrary data from one to the other. Most implementations I have seen (signals and slots) require that there be some reference to each other. Creating a "middle-man" interface feels much more flexible.
Thank you for your time.
For reference to my last question with code examples of what I have so far:
Store a function with arbitrary arguments and placeholders in a class and call it later
I have more samples I could post, but I think it's highly likely that the structure of the system will have to change. Waiting to hear thoughts!

Creating a new c++ object from within a lua script?

---Context---
I want to have a class called "fileProcessor". This class is completely static and merely serves as a convinient namespace (within my normal library namespace) for some global function. This is a basic blueprint of the class with only the relevant stuff
class fileProcessor{
private:
lua_State* LUA_state;
public:
static std::variant<type1,type2> processFile(const char* filePath,const char* processorScript);
}
Please note again that I ommitted most of the stuff from the class so if anything seems odd ignore it.
What process file is supposed to do is:
Read the filePath file, storing all directives including it (this is my own filetype or style of syntax. This is already handeled correctly). The directives are stored with strings, one for the command and one for everything after it.
Read the script file and check if it has a commented out fileProcessor line at the top. This is to make sure that the lua script loaded is relevant and not some random behaviour script
Load and compile the lua script.
Make all read directives available (they are saved in a struct of 2 strings as mentioned before)
Run the file and recieve a object back. The object should only be of types that I listed in the return type (variant)
I am having problems with step 4 and one vital part of the scripting.
---Question---
How can I make the creation of a full new object of type1 or type2 possible within lua, write to it from within lua and then get it back from the lua stack into c++ and still know if its type1 or type2?
---No example provided since this question is more general and the only reason I provided my class is for context.---
It seems like you are trying to do it the other way around. I quote a part of this answer:
...you are expecting Lua to be the primary language, and C++ to be the client. The problem is, that the Lua C interface is not designed to work like that, Lua is meant to be the client, and all the hard work is meant to be written in C so that Lua can call it effortlessly.
If you are convinced there is no other way that doing it other way around you can follow the workaround that answer has given. Otherwise I think you can achieve what you need by using LUA as it meant to be.
LUA has 8 basic types (nil, boolean, number, string, userdata, function, thread, and table). But you can add new types as you require by creating a class as the new type in native C++ and registering it with LUA.
You can register by either:
Using some LUA helper for C++ like luna.h (as shown in this tutorial).
Pushing a new lua table with the C++ class (check this answer).
Class object instance is created in your native C++ code and passed to LUA. LUA then makes use of the methods given by the class interface.

Performing "true" dynamic casts at runtime?

So I am still working on a flexible scripting system for this school project and have come to a road block. The problem is this: I have a script state manager interface that any scripting state will implement (currently implementing lua, but want to be able to add python later). It has pure virtual functions for things such as DoFile, DoString, RegisterObject and RegisterFunction. So the LuaStateManager implements this interface using luaplus classes and encapsulates the LuaState object as it should.
So when an object registers itself with lua and throws all its methods into a metatable I have to do something like this:
metaTable.RegisterObjectDirect(“Move”, (Actor*)0, &Actor::Move);
This would be fine if I had access to the underlying state object in the StateManager interface as it would be getting called from the Actor class itself so the cast could be guaranteed. Unfortunately, I need to somehow pass this info to the LuaState::RegisterFunction method so the I don't have to expose the LuaState object and couple my classes to it. As far as I can see though, there is no way to pass information about which type of class to cast to.
Does any body have any suggestions? I thought about trying to use a templated function to perform the cast, but I know that you can't have function pointers to templates, so that is out the window. Thanks!

Passing existing C++ objects to Lua and calling the passed objects' member functions

I'm working on a little simulation project which uses Lua to drive the behavior of individual units (ants) and using Luabind to glue the C++ and Lua sides together. Each individual ant (there are different types, derived from the base class Ant) has a Run() function, which calls the appropriate script; the script then carries out whatever actions need to be taken, calling the exposed class functions and possibly free functions. I've gotten the Run function (in C++) to successfully execute the matching Run function in the Lua script (which just prints some text at the moment).
void AntQueen::Run()
{
lua->GetObject("QueenRun")(GetID());
}
lua is just a manager class which retrieves the function from the script. The above is calling the following in a Lua file:
function QueenRun(ID)
print("The Queen is running!")
print(ID)
end
And Luabind registration looks like this for the AntQueen class:
void Register(lua_State *luaState)
{
using namespace luabind;
module(luaState)
[
class_<AntQueen, Ant>("AntQueen")
.def("Eat", &AntQueen::Eat)
.def("ExtractLarvae", &AntQueen::ExtractLarvae)
.def("GetMaxLarvaeProduced", &AntQueen::GetMaxLarvaeProduced)
.def("GetNumAvailLarvae", &AntQueen::GetNumAvailLarvae)
];
}
The way it's set up now, ants are created, removed, and found through a simple factory/manager. Each ant can be retrieved by calling static Ant* AntFactory::GetAntByID(const int ID) which just finds the ant in a hash map and returns a pointer to the ant. What I'm trying to do is get Lua to be able to do something like the following:
function QueenRun(ID)
ant = GetAntByID(ID)
larvae = ant:GetNumAvailLarvae()
print(larvae)
ant:Eat()
end
The above is just a made up example, but hopefully it shows what I'm trying to achieve. I don't want Lua to garbage collect the objects, because they are managed already on the C++ side. While testing everything out, any attempt to do the following:
ant = GetAntByID(ID)
in Lua resulted in abort() being called and the program crashing and burning.
R6010
-abort() has been called
I just seem to be missing something with how everything gets shuttled back and forth (this is my first foray into gluing Lua and C++ together beyond toy programs). I'm pretty sure passing a plain pointer isn't the way to do it; lightuserdata seems to be what I'm looking for, but it also has a bunch of restrictions.
So to sum up: What is going on here that causes abort to be called and how can I use Luabind/the Lua C API to get a pointer to a C++ object passed to Lua and call member functions on that pointer as if it were an object (without letting Lua garbage collect it)?
The solution to this problem seemed to be tied to the AntFactory class/member functions being static. As soon as I switched from registering and using this:
//C++
static int AntFactory::CreateAnt(foo, bar)
{}
//Lua
factory:CreateAnt(foo, bar)
to an instantiated object and regular member functions like this:
//C++
int AntFactory::CreateAnt(foo, bar)
{}
//Lua
factory:CreateAnt(foo, bar)
everything worked with no problems at all (after also pushing the factory to the global table). I think the reason for this is that trying to call static member functions on a non-instantiated C++ object fails due to Lua (or Luabind?) not being able to have an object to query for calls.