I'm having problems with luabind. I define a std::map to allocate objects created in lua. I publish this map as a global object in lua in this way:
luabind::globals(L)["g_SceneManager2D"] = this;
After that, this object is used into a function into lua, where many objects are created and inserted into this map. The problem comes when lua function ends and luabind returns the control to C++ side program, because automatically all contents of the map are lost.
I was looking for the error. I keep the lua context alive, so this object must exists.
Could you helpme??
Many thanks :)
I suggest use a shared_ptr<>(this) rather than raw this. boost::shared_from_this might help. Make sure your class is registered using Luabind too, and that the class_ is specified as held by a shared_ptr.
Another fun idea might be to make your Lua function just generate the "map" as a Lua table, return it, and you can iterate over it in C++ to build your std::map.
If I understand your problem correctly, it seems you are creating objects in Lua, which you then insert into the map (either through Lua or C++) and subsequently lose. Without some more code, it's hard to tell exactly what the problem is. However, I would first look to make sure that those objects are indeed being created (double check it) and then I would check to see that Lua isn't garbage collecting them. If Lua is indeed garbage collecting those objects, then you won't see them on the C++ side because they're, well, gone.
If it helps, I'm finishing up a project which does something similar. I had to create and retrieve C++ objects from Lua, but instead of creating the objects in Lua, I just called C++ functions to do it for me, sending any necessary data in the Lua call (bound by Luabind). Those (C++) functions indexed the objects by IDs into hash tables and the IDs were returned to Lua in case it needed to retrieve the object script-side for operations. This setup makes it easier (and safer) to handle memory stuff correctly and prevents Lua from garbage collecting your objects.
Related
Say I have the address of a table - how would I "cast" a table variable to it? I'm not concerned about "bad practice" or crashes because this is just an individual problem.
I want to do something like
lua_table tab = *(lua_table*)0xaddr
...but within the Lua global environment.
I understand how bad this is but I really need to know if this is possible. It may not be the best way to do what I'm trying to do, but I'm quite certain it's the easiest and that it will work if this is possible. I am using Lua 5.1.4.
Lua exposes no API for doing this.
It would be easier and much more robust to fix your design rather than trying to force this to work.
In order to do what you're attempting, you must:
Get a pointer to the Lua table's data structure. I'm sure you believe that you already have such a pointer. But there's nothing in Lua that guarantees that the pointer you have obtained (through some means) is actually a pointer to the table data structure. It could be a pointer to something else. So you need to hunt through Lua's internals to make sure that wherever you're getting this pointer from is giving you a pointer to the actual object.
Find the correct type, declared within Lua's internals. There is some C type (Lua's written in C, not C++) that Lua uses to represent the main table data structure. You will have to track down this struct definition and use that.
A cursory examination of the Lua library suggests that the main table data structure is defined in lobject.h, under the name Table.
Find the internal APIs that Lua uses to manipulate this table correctly. It's obviously some kind of hash table, but you're going to need to use Lua's functions to actually do anything with it.
A cursory examination of Lua's internals suggests that this code would be found in ltable.h. However, there are probably more APIs than that. Also, do note that many of those APIs take a lua_State, so they may be doing some stack fiddling.
You will also need to look through Lua's API so that you can learn how to use them without breaking the table. Lua may have certain expectations about when certain functions are called or the order between them or whatever. Break these at your own peril.
Even then, this:
Table tab = *(Table*)0xaddr
Will never work. Or at least, not the way you mean for it to. Lua is written in C. Which means that Table is not going to work like a C++ value type. Copying it will only do a bitwise copy. So modifying tab will only modify your local copy of those values. If those are pointers to other data structures, that may be OK, since your pointers and the original pointers point to the same data structures. But if you perform some operation that changes the Table::flags field on the table, for example, the table stored in Lua will not be affected, only your local tab copy will be.
You have to manipulate the object as a pointer, not a copy of the original.
Table *tab = reinterpret_cast<Table*>(0xaddr);
Is it possible that luabind checks, if a member function call to an exported class (object) is for a valid object?
lets assume that i have a Class called Actor exposed using luabind to lua. Im calling a lua function from C++ with an actor object as parameter. Now before the function finishes, a script write would put the actor object in a global lua reference to be accessed later.
Later on, the actor object is deleted from the C++ site, another function is called which tries to access the invalidated actor object (any method from it) - and obviously since it has been deleted, it results in a crash (access violation)
sample:
local myObjRef = nil
function doSomethingWithActor(actor)
-- save, still valid object
actor:Say("hello")
myObjRef = actor
end
function calledAfterActorWasDeleted()
--- will crash if the c++ object has been deleted meanwhile, works fine if it still exists
myObjRef:Say("Crash...")
end
A NIL check doesnt help here, is this something that can be checked on luabinds site? The functions are executed using lua_pcall(....) and the stacktrace shows the error at luabinds call.hpp results = maybe_yield(L, lua_gettop(L) - arguments, (Policies*)0);
If not, is there another solution how to make sure somebody who writes a script cannot create these issues?
Now before the function finishes, a script write would put the actor object in a global lua reference to be accessed later.
That right there is where your problem is coming from. If you want Lua code to own the object (that is, preserve the existence of this object), then you need to use Luabind mechanics to tell Luabind that you want to do that. Otherwise, if you pass a pointer to some Lua function, Luabind will assume that the function will not be trying to gain ownership of it.
If you want ownership to be shared between Lua and Luabind, then you should wrap your objects in a boost::shared_ptr, and use Luabind's smart pointer mechanisms to do this.
You could also simply segregate your scripts better. If you have some script that operates on a particular actor, then that script and any functions it contains should be destroyed (ie: lose all references to it) along with the object. This requires proper coding discipline on the C++ side. It will also require that you use Lua environments to properly encapsulate each instance of a script, so that they can't sneak things out via globals. Lastly, you will need to have C++ maintain total control over when scripts are called and when they aren't.
Otherwise, ownership is something your scripters are simply going to have to know about and be careful of. They can't treat C++ parameters like any old Lua value.
If exercising disciplined programming practice is not possible or practical for you, then you will simply have to not pass Lua the actual C++ object. Instead, you need to pass Lua some proxy object, which is a reference to the original. boost::weak_ptr is a good example of such an object (though you wouldn't pass it exactly to Lua). The proxy would forward calls to the actual object. If the object has been deleted, the proxy would detect this and fail or do nothing or whatever.
I solved my issue the following way:
When im about to delete an object, i iterate through all lua functions from C++ (i have them in a list, they are bound to specific actor objects each). Then i inspect each upvalue (global/local vars accessable to a function) - then i compare the userdata pointer with my object im about to delete - if they match (and their classes) and NIL the upvalue. Optionally, i could just remove that offending function because it would not work well anymore anyway.
So the next the time the function is called, im just getting a soft lua error "trying to access xxx a nil value..." - no more access violations.
I know people would say "dont use lua_getupvalue/lua_setupvalue - they are only for debugging!" - but there is actually no documented or spoken side effect - and in my case its perfectly safe and works well - also there isnt the issue with left over proxy objects i could not delete.
I'm implementing Lua scripting in my game using LuaBind, and one of the things I'm not clear on is the logistics of reloading the scripts live ingame.
Currently, using the LuaBind C++ class luabind::object, I save references to Lua callbacks directly in the classes that use them. Then I can use luabind::call_function using that object in order to call the Lua code from the C++ code.
I haven't tested this yet, but my assumption is that if I reload the scripts, then all the functions will be redefined, BUT the references to the OLD functions will still exist in the form of the luabind::object held by the C++ code. I would like to be able to swap out the old for the new without manually having to manage this for every script hook in the game.
How best to change this so the process works?
My first thought is to not save a reference to the function directly, but maybe save the function name instead, and grab the function by name every time we want to call it. I'm looking for better ideas!
My first thought is to not save a reference to the function directly, but maybe save the function name instead, and grab the function by name every time we want to call it.
If your classes are calling global functions with known names, then that pretty much solves your problem. No need to grab a reference in advance; it's not going to make a measurable performance difference. I think call_function supports passing the function name as a string anyway, right?
You typically store reference to a function value when the Lua script is registering a callback. In that case, it's much better than storing a name, because it allows the Lua script to register functions which are local, anonymous, ect.
If you really had to grab the value value in advance, as you're doing now (and there's really no reason to do that, but we'll pretend it's necessary), I would add a layer of indirection. You could have a LuaFunctionReference class which encapsulates a global name. During instantiation, it grabs a reference to the function the global contains. These objects could be acquired from a factory which maintains a list of all such references. When you reload a script, you could have the factory/manager/pool/etc. object iterate through the references and have them update themselves, so all the references tucked away in classes throughout the system would be updated.
I am trying to embed lua in an existing C++ application and have made a standard procedure for it by inheriting from a class that does the work.
The serious problem I see is that if the exposed object gets deallocated or deleted in the C++ environment then a call from Lua will cause crashes. If the memory is being deleted by the program using 'delete' then I can maybe write a wrapper on delete to take care of deallocation in Lua as well, but if the memory was allocated by C++ and deallocated when the appropriate variable is out of scope I don't see a way on how to find that out and then take appropriate actions in the lua space, anybody has any ideas on this?
Thanks.
In general, virtually every Lua wrapper has some way to decide who owns what memory. That is, whether an object is owned by (and therefore will be deleted by) Lua or by your application.
If you have given Lua a pointer to an object that C++ owns, then you must find a way to ensure that Lua does not use this pointer past the point where C++ deletes it. There are several ways to avoid this. One way is to transfer ownership to Lua.
Another way is to use a boost/std::shared_ptr, which allows you to share ownership between C++ and Lua. If you're manually doing this, then you are creating some non-light userdata which is the size of a shared_ptr in Lua. You attach a cleanup metamethod to it that will destroy the shared_ptr, and you use placement-new to construct the shared_ptr on the Lua userdata. Luabind actually has this built-in as a feature: if you pass a shared_ptr to Lua, then they both share ownership of the memory.
You could also use a boost/std::weak_ptr. This is an object that you query to get a shared_ptr. The idea is that you're not supposed to keep the pointer around; you query it temporarily as needed, but you only store the weak_ptr permanently. If the object has lost all of its shared_ptr references, then querying the weak_ptr will return a null pointer.
You will have to use an RAII wrapper that can bind to the Lua instance using the registry and expose the values to Lua using a table- you can remove an internal pointer from it when you're done.
template<typename T> class LuaExposedValue {
T t;
lua_State* ls;
public:
LuaExposedValue(lua_State* L) {
// set registry[&t] = { &t }
ls = L;
}
~LuaExposedValue() {
// remove &t from the table
}
}
Alternatively, just ban Lua from accessing it after the variable is gone and let the scripter worry about it.
Finally, you could just allocate everything that Lua can access using the Lua GC.
Disclaimer: I wrote the library I'm about to recommend
You might want to try using this LuaWrapper Library that sounds like it'll handle what you're trying to do. It's not even really a library, it's just a single header file.
You can use luaW_push<MyType>(L, myObj); to push your objects into Lua. Lua will not own the objects you create from C++ unless you run luaW_hold<MyType> on them. In other words, unless you tell Lua to, it will not garbage collect your object.
Conversely, you can use MyType.new() in your Lua code to create an object, which Lua does own. It will be garbage collected as you would expect. If you want to pass ownership to C++ you can call luaW_release<MyType> on your object.
There's also functions like luaW_to<MyType> and luaW_check<MyType> and to a limited degree it correctly supports inheritance from base types (though at the moment it only allows for single inheritance). I find that this greatly simplifies my own attempts at using C++ and Lua together because it make managing pointer ownership very straightforward.
I successfully integrated Lua into my C my application, giving scripting access to users. Now my problem: how can I prevent double free or bad access violations?
I already implement Init and Free functions for each struct, for example:
structaInit
structaFree
I also track every time a struct pointer is linked to another, incrementing the reference count which is present in all of my structs.
However the users could always do something like this in Lua:
a = structaInit();
b = structbInit();
structbSetA( b, a ); -- This add ++a.reference
a.reference = 0;
a = structaFree( a ); -- If a->reference == 0 then I free
-- Then struct b->a is still a valid pointer but that have been free.
Is there anyway I can prevent this from happening?
The problem has to do with ownership. Let's take your Lua scripts:
a = structaInit();
b = structbInit();
This creates C objects that Lua now owns. Lua will decide when to free the memory for these objects.
So what about this?
structbSetA( b, a ); -- This add ++a.reference
First of all, structbSetA should be a member of b, via a metatable (so it becomes b:setA(a)). But more importantly, who owns a?
Lua does. Because it must own A; Lua cannot fully relinquish ownership of an object that is still in Lua memory. This means that your internal reference count is ultimately meaningless; the only one that matters is Lua's.
If you intend to store the value of a within b, such that b can reference a so long as b is still alive, then you need to create this relationship through Lua methods. You can't just stick the C pointer to a in b and expect everything to go well.
The easiest way to do that is to, for each object you create, make a table in the Lua registry that stores the Lua object for any references it has. When an object is destroyed, you go into the Lua registry and remove this table from it, thus leading to the destruction of any referenced Lua objects. Obviously, you will need to change this value when it is modified by later calls to structbSetA.
Also, why are you exposing this to Lua:
a.reference = 0;
That's a terrible API. Lua code should never have to deal with a reference count. You should also never expose an explicit "free" method to Lua, unless you need Lua to release some resource immediately after it is finished using it. And that should only be necessary for OS-type resources like FILE handles and such. For a regular object, let the garbage collector do its job.
Do not expose C-isms to Lua code. Let Lua code look like Lua code.
In this case it comes down to programming practice you do not really want to prevent it, you actually want to let it error out because that way the person using your scripts knows that they are doing something wrong (same way in obj-c it crashes when you over-release). If you don't want this to happen you might have to keep track of all active pointers on the heap to your structs in a linked list or some structure but I don't think it's worth it.