lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


> Suppose I have an object that is allocated  (created) in Delphi (or C++ 
ro whatever). I don't (can't) want to give Lua full  control on the 
object's life, I just want to  give access to its properties via  properly 
set callback functions in metatable of a heavy user data, that I wrap this 
object into for Lua.

> Now the object gets destroyed (in Delphi), that  brings the possibility 
of calling property access function with a pointer to  already freed 
object if I have some heavydata references to this object left in  Lua.

> Any ideas if I can somehow avoid this? Ideally  would be me being able 
to track down all userdata that points to this object and  nil them out in 
Lua, but I can't think of the way how to make it automatically,  without 
thorough keeping track of references by hand. Or maybe I can do it some 
other way around?

If I'm not mistaken, there has been quite a lot of discussion of this 
issue lately.

My favorite solution: Keep a table in the registry keyed by the address of 
the Delphi object, whose values are the heavy-user data. You can use this 
table to ensure that there is only a single Lua reference to each Delphi 
object. When you delete the object in Delphi, set a flag in the relevant 
userdata, using the address of the Delphi object to lookup the Lua object 
in the registry table [1] or alternatively, set the userdata's contents to 
NULL. This does not cause the Lua object to become nil, but it makes it 
possible for Lua to check the object for validity. Once you have flagged 
the userdata, *remove the key from the registry table*. (This is 
important, both to allow the Lua userdata to be garbage collected, and 
because the object's address may be assigned to a new object.)

The userdata will have a metatable; you can use this to identify the 
object's class. This is handy because it allows you to check the class of 
an object from C as well, simply by looking the address of the object up 
in the registry table and then getting the metatable out of the resulting 
userdata. So you get a form of run-time inspection without having to 
modify the C definition of the object.

You still have a problem if there is some mechanism by which objects can 
be deleted from the Delphi environment without you being informed of that; 
this might be the issue for an object which has a non-Lua garbage 
collection method, such as reference counting. That is more difficult to 
solve; garbage collection methodologies don't easily co-operate with each 
other. Hopefully if this is the case, the C-side memory management system 
will also provide you with a finalisation method.

[1] Use lightuserdata for the keys; a lightuserdata is guaranteed to be 
big enough for a pointer. Also, you do not technically need a separate 
table; you can simply use the registry as long as you follow the 
convention (followed by the Lua libraries) that a lightuserdata used as a 
key in the registry is always the address of allocated storage.