lua-users home
lua-l archive

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


Am 07.01.2015 um 16:48 schröbte Oliver Kroth:
Hello Vyacheslav,

Hi!


when you sue userdata, the Lua VM will allocate (and free) the memory.
You may possibly go better with light userdata, which is actually a
pointer to something you maintain.

Or you use a pointer-sized full userdata (like the OP already does) and avoid the following problems:

__gc will still be called when the Lua VM does no longer references the
data, but it will not free then memory.

No, lightuserdata are not garbage-collected, and no `__gc` metamethod is called. Also you don't get individual metatables, so you can handle one type of lightuserdata at most.

This way you get the chance to let your objects live longe than Lua uses
them, and share the same object among several variables (even in
different Lua VMs if you handle concurrency correctly)

--
Oliver

Am 07.01.2015 um 15:42 schrieb Vyacheslav Napadovsky:
Hello.

I'm trying to integrate lua into my program. I have a bunch of objects
and their userdata's.
Each object's userdata only holds a pointer to a C++ object (4 bytes
on a 32-bit OS).
I use the reference counting system to determine when to delete the
C++ objects (Addref/Release)
(The lifetime of C++ object is longer than Lua userdata)

Every C++ object has its own userdata in Lua. I create userdatas when
needed (and call Addref on the C++ object).
Moreover, if I want to load C++ object into Lua once more I need to
use the same userdata
(to make '==' operator work correctly). For this purpose I've created
a table in LUA_REGISTRYINDEX.
The table has __mode=='v', and when I load object into Lua I check
    if (table[this] ~= nil) then  -- actually I use lua_rawgetp(L,
table_idx, this) in C++ code
        I use userdata from this table
    else
        I create lua_newuserdata and save it in this table (lua_rawsetp)
    end

When Lua's userdata __gc metamethod is called I have to decrement the
object reference (Release) and
(probably) clear the reference for the userdata from the table:
table[this] = nil.

The question is: should I do this:  table[this] = nil ?

No, you don't have to do this. The values that are about to be garbage collected are cleared from weak-valued tables before the `__gc` method is called (and from weak-keyed tables after the `__gc`). (See here[1].)

And is that overall a correct way to propagate C++ objects to Lua?

Yes, that sounds like a reasonable approach.


P.S. If I do (table[this] = nil), I sometimes get 2 userdatas pointing
to the same C++ object.

Then don't do that. The garbage collector should have cleared that entry before calling the finalizer anyway, and maybe you are removing a new value that should have stayed in there. Also note that the `this` pointer might be different for different methods on an object (depending on which class they are defined in).

P.P.S. How to get to know that __gc metamethod has been called for
this particular userdata from C code?

A common approach is to set the pointer in your full userdata to `NULL` in your finalizer.


I use Lua 5.2.3.

Best regards,
Vyacheslav.


Philipp


  [1]: http://www.lua.org/manual/5.2/manual.html#2.5.2