Question

I'm wondering if it's possible to access all of the userdata "tables" (is it called userdata tables?) and then delete them from Lua because this is my problem:

a = Object(5, 5)
a:Delete()
a:SetPosition(3,3)

As you can see first I create an object and save an pointer to a c++ class called Object which is allocated using "new" in my map class. Then I delete the object which means I delete the allocated memory for the pointer in my map class. And last I call SetPosition, if the memory still is allocated for the c++ Object class everything will run fun. But if it is deletes (as it is in this case because we called Delete() before the SetPosition(...) call) my program will crash. So what I'm wondering is following:

Is it possible to set the varaible 'a' in lua to nil by calling Delete ? I know I could do something like 'a = a:Delete()' if Delete return nil but if I forget to do the 'a =' part it fail. Also I'm wondering if it's possible to delete the userdata and check if it doesn't exist when I call SetPositon(), if it doesn't I will just return.

Also, the base code is from: http://lua-users.org/wiki/SimpleCppBinding

Was it helpful?

Solution

In the Delete method, set the metatable of the received object to nil and you'll get an error message if you later call a method on that object.

OTHER TIPS

First, let me answer your question:

Is it possible to set the varaible 'a' in lua to nil by calling Delete ?

No. There is no means to do what you're saying. And there's a reason for that: what you're trying to do is terrible code.

Lua is a garbage collected system. Lua should not be expected to delete objects. If Lua gets a pointer to some external object, then either your code owns it or Lua owns it.

If your code owns it, Lua should not be deleting it. Lua can use it for some period of time. But it is up to your Lua code to use it for exactly and only that period of time. Once its lifetime has expired, Lua shouldn't be talking to it anymore.

This is no different from dealing with pointers to objects in C and C++. If your function is handed a naked pointer (ie: not a smart pointer), your code needs to know how long it can reasonably expect to talk to that object. Can it store it? How long can it store a pointer to that object? When will that object die, and who's responsible for destroying it?

If you pass an object to Lua such that Lua now owns the object, Lua shouldn't be explicitly deleting it either. Lua is a garbage collected system; you should attach a __gc metamethod to your type, so that Lua's garbage collector will call your code when the userdata is collected. That way, you can call destructors, free memory, etc.

When you give Lua something that now belongs to Lua, it should look like a regular Lua object. You don't call Delete methods for tables and strings you create in Lua; you let the garbage collector do its job. It is your job, as the one writing the C++-to-Lua interface, to ensure that the objects you give to Lua behave the way that Lua wants them to.

In cases where you need to do significant resource management, where you want Lua to release resources as quickly as possible (such as for file handles, etc), then you need to store a pointer to your C++ object inside of the non-light userdata. That's the pointer you NULL out. All of your interface functions on that object will check the pointer to see if it's NULL and simply do nothing or raise an error.

Lua's file handles (returned by io.open) are a good example of this. If you try to call functions on them, Lua throws a Lua error.

I'd rather advice using SWIG or LuaBind instead, they've already taken care of such pitfalls for you.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top