What is the difference between Lua registry with l

2019-07-12 22:45发布

问题:

So with the Lua C API you can save a Lua value in the registry and retrieve it later. There are different ways to do it, you can create a variable and use it's pointer as the key in the registry as it's always unique. You would push the pointer as light userdata.

You can also create a reference using LuaL_ref(L, LUA_REGISTRYINDEX). What is the advantage of one over the other? When to use references and when to use pointers?

Also with references, as it is called a reference, if the Lua garbage collector collects the Lua value, will the value in the registry be nil? What if Lua updates the Lua value, will the value in the registry also change?

回答1:

Lua registry is just another lua table, easily accessible via predefined "special" index. I guess you don't need explanations on how Lua table is different from light userdata.
It doesn't really matter how you will index registry table, as long as you can store that key on C/C++ side. For your convenience there's already functions (luaL_ref/luaL_unref) giving you integer key that is easy to store and move around.

About garbage collection - rules are always the same. As long as value is stored in table that wasn't marked as weak table (registry is not weak table), that value won't be cleared. You must explicitly remove value from the registry.

Changing value will obey normal Lua rules. Assigning new immutable value to some variable won't change value stored in registry, i.e. registry won't follow updates to some variable. But changing content of mutable value (table etc) is ok, since registry and variable will refer same value.



回答2:

In addition to previous answer:

Differences between Lua lightuserdata and userdata

lightuserdata is a special Lua type (as well as nil, boolean, number, string, table, thread etc.) containing C pointer. Nothing more. You can't assign metatable to lightuserdata. On the contrary, you can assign metatable to userdata type. For example see Lua File operations, where file handle is userdata with methods. f:read("*all") f is userdata the command is equivalent to f.read(f, "*all")

Indexing LUA_REGISTRYINDEX with integer or C pointer

There are two methods that are widely used on registry table.

  1. Create new reference to Lua value with luaL_ref and store the return integer value somewhere in your code. I.e. to access the Lua value you'll need to read C variable holding the reference and index registry table with lua_rawgeti(L, LUA_REGISTRYINDEX, i) where is that integer value. lua_rawseti(L, LUA_REGISTRYINDEX, i) is also possible, but don't try rewrite to a nil value with this method!

  2. You creating a static C variable static int myvar; and then use lua_rawgetp(L, LUA_REGISTRYINDEX, p) and lua_rawsetp(L, LUA_REGISTRYINDEX, p) for manipulation of stored Lua value straight-forward.

Unfortunately I can't compare the performance of both methods. I think they are almost the same.