[LuaAPI] Using a metatable as an index??

Started by
9 comments, last by Sneftel 19 years, 6 months ago
Hi, let's say I have... lua_pushstring(L,"myarray"); lua_rawget(L,LUA_REGISTRYINDEX); luaL_getmetatable(L,"whatever"); lua_rawget(L,-2); where myarray = {} and whatever is a valid metatable. The final command confuses me. Is it looking for a table entry for the metatable index? If this index thus converted to a number or string? lua_newtable(L); luaL_getmetatable(L,name); lua_pushvalue(L,-2); lua_rawset(L,-4); How about this? Many Thanks algorhythmic
[email=algorhythmic@transcendenz.co.uk]algorhythmic[/email] | home | xltronic | whatever you do will be insignificant, but it is very important that you do it - mahatma gandhi
Advertisement
You first code will do something like this:

- pushes "myarray" string on the stack
- rawget replaces the "myarray" stack entry with a value assigned to "myarray" key in the registry table
- getmetatable method won't work, because it doesn't accept string as an argument. The second argument should be a stack index of the table you want to get the metatable of. But since the only thing on a stack is myarray table, the only legal index is -1. This will push the metatable of myarray on the stack. If it is an empty table without any metatable assigned, it won't push anything and return 0.
- rawget is supposed to index myarray using it's metatable as a key. But if myarray has no metatable, it causes stack underflow, because there's only one item on the stack.

If you were trying to index a table with another table (or metatable, as long as it's represented by a regular table), nothing would be converted. This is a big power of tables in Lua - you can index them using any value / object. This is especially useful for creating unique keys. Like this:

uniquekey = { };
table[uniquekey] = something;

Your second code creates a new table. If "name" is -1 integer, the only valid stack index, it pushes the metatable of your new table, but since your new table doesn't have any metatable yet, it doesn't push anything. So the rest of the code is not valid.
Society's never gonna make any progress until we all learn to pretend to like each other.
Well for one the code must be correct as it's pulled straight from toLua. luaL_getmetatable takes a const char* name and a metatable for this name does exist.
Quote:If you were trying to index a table with another table (or metatable, as long as it's represented by a regular table), nothing would be converted. This is a big power of tables in Lua - you can index them using any value / object. This is especially useful for creating unique keys. Like this:

uniquekey = { };
table[uniquekey] = something;

This answers my question. What would be the best way of showing the content of table in text of diagram form?

Many Thanks

algorhythmic
[email=algorhythmic@transcendenz.co.uk]algorhythmic[/email] | home | xltronic | whatever you do will be insignificant, but it is very important that you do it - mahatma gandhi
Oh my yes, I have mitaken "lua_getmetatable" for "luaL_getmetatable". Sorry.

I looked at the source code of lauxlib.c:
LUALIB_API void  luaL_getmetatable (lua_State *L, const char *tname) {  lua_pushstring(L, tname);  lua_rawget(L, LUA_REGISTRYINDEX);} 

So it just pushes a value of *tname string index in registry table. Too bad I don't have any documentation to the auxiliary library, I guess that's just helper function to store metatables in the registry...

To show contents of a table, I would do this:
for k, v in table do print(tostring(k) .. " -> " .. tostring(v));end

However, this is only good for debugging purposes. It would be much harder to do some kind of a table serializator...
Society's never gonna make any progress until we all learn to pretend to like each other.
One last question, When going through the lua sources I noticed a few comments:

registry.name = metatable
and registry[metatable] = name

what's the difference between the . and the [] ?

I ask this in connection with luaL_newmetatable(L,name). Could you explain what it actually does?

Many Thanks
[email=algorhythmic@transcendenz.co.uk]algorhythmic[/email] | home | xltronic | whatever you do will be insignificant, but it is very important that you do it - mahatma gandhi
Why certainly!

table.index is the same as table["index"], that is, indexing using actual string "index"
table[index] is indexing using value of variable index

The table can be indexed with any value. Indexing using dot is just a syntax synonym for indexing using string constant. It is done this way to help programmers, so they don't have to write too much... indexing using string constants is widely used for representing data structures for example.

I don't know what luaL_newmetatable does; I don't use it. But I noticed it contains the two lines of yours, so I will try to explain them.

Let's say you have a metatable called "mt" (please note that a metatable doesn't need names, this is just a helper mechanism of the auxiliary library). The code assigns the actual metatable using it's name as an index and then assigns it's name using the metatable as an index. After that, if you have a metatable and want to retrieve it's name, you can do (in C API of course, in LUA you have no access to the registry table):

mtname = registry[mttable];

And when you know the name and want to obtain the metatable:

mttable = registry[mtname];
Society's never gonna make any progress until we all learn to pretend to like each other.
Ok that certainly clears that up. Thanks. I just have difficulty seeing in what way the product of the luaL_newmetatable method is a metatable and not a standard table. I fail to see what makes the table it creates a metatable.
[email=algorhythmic@transcendenz.co.uk]algorhythmic[/email] | home | xltronic | whatever you do will be insignificant, but it is very important that you do it - mahatma gandhi
Metatables are standard tables. The only difference is that you define certain fields of it and assign it to another table. Be sure to check the Lua reference manual.
Society's never gonna make any progress until we all learn to pretend to like each other.
Yes I know this but at no point does the luaL_newmetatable method set the metatable so for all intents and purposes it's a normal table right? If that's the case then it's pretty misleading method name unless I'm missing something...
[email=algorhythmic@transcendenz.co.uk]algorhythmic[/email] | home | xltronic | whatever you do will be insignificant, but it is very important that you do it - mahatma gandhi
I think it's just an auxiliary mechanism for storing metatables using names. Of course you can use them as regular tables, but that would be pretty useless because IMHO if you want to store some table naming it, it would be a metatable for some kind of library written in Lua C API.
Society's never gonna make any progress until we all learn to pretend to like each other.

This topic is closed to new replies.

Advertisement