lua-users home
lua-l archive

RE: Using tables from the C API

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


Thanks! That got me past the user data question. My next question is to see if I understand how to work with tables from within the C API.
Here's a C function that should take a string and a table.
1. Error if the first argument is not a string.
2. Error if the second argument is not a table.
3. Error if there is not a "name" field in the table.
4. Append the string to the "name" field in the table.
5. If there is not a "type" field in the table, add a "type" field with the value of "default".
When I run the script, I get the results that I'm expecting. Is my approach from the C side a sound approach?
------------------------------------------------------------
-- lua script. src is set to a class from the API
--
t = {name="foo"}
print("t.name", t.name)
print("t.type", t.type)
src:SillyFunc("x", t)
print("t.name", t.name)
print("t.type", t.type)
------------------------------------------------------------
-- output
--
t.name foo
t.type nil
silly: suffix is 'x'
silly: top of stack is 'foo'
silly: concat stack is 'foox'
silly: field stack is 'name'
silly: stack is 'foox'
silly: field stack is 'foox'
silly: stack is 'name'
silly: not of stack is 'foox'
t.name foox
t.type default
//----------------------------------------------------------
// C API
//----------------------------------------------------------
// SillyFunc(string, table)
//
int CSV_silly(lua_State *L) {
 // stack: 1 -> table myCSV
 // : 2 -> string "x"
 // : 3 -> table {name="foo"}
 // first argument must be self
 myCSV *csv = (myCSV *)luaL_checkudata(L, 1, libName);
 // second argument must be string
 const char *suffix = luaL_checkstring(L, 2);
 printf("silly: suffix is '%s'\n", suffix);
 // third argument must be table
 if (!lua_istable(L, 3)) {
 error(L, "we demand table for 3rd parameter");
 return 0;
 }
 const char *key = "name";
 // get field value from the table
 lua_pushstring(L, key);
 // stack: 1 -> table myCSV
 // : 2 -> string "x"
 // : 3 -> table {name="foo"}
 // : 4 -> string "name"
 lua_gettable(L, 3);
 // stack: 1 -> table myCSV
 // : 2 -> string "x"
 // : 3 -> table {name="foo"}
 // : 4 -> table.foo which is string "foo"
 // confirm that we have a value for that field
 printf("silly: top of stack is '%s'\n", luaL_checkstring(L, -1));
 // stack: 1 -> table myCSV
 // : 2 -> string "x"
 // : 3 -> table {name="foo"}
 // : 4 -> string "foo"
 // concatenate the suffix to the field
 lua_pushstring(L, suffix);
 // stack: 1 -> table myCSV
 // : 2 -> string "x"
 // : 3 -> table {name="foo"}
 // : 4 -> string "foo"
 // : 5 -> string "x"
 lua_concat(L, 2);
 // stack: 1 -> table myCSV
 // : 2 -> string "x"
 // : 3 -> table {name="foo"}
 // : 4 -> string "foox"
 // confirm that the concat worked
 printf("silly: concat stack is '%s'\n", luaL_checkstring(L, -1));
 // stack: 1 -> table myCSV
 // : 2 -> string "x"
 // : 3 -> table {name="foo"}
 // : 4 -> string "foox"
 // update the table with the concat'd value
 // push the field name
 lua_pushstring(L, key);
 printf("silly: field stack is '%s'\n", luaL_checkstring(L, -1));
 printf("silly: stack is '%s'\n", luaL_checkstring(L, -2));
 // stack: 1 -> table myCSV
 // : 2 -> string "x"
 // : 3 -> table {name="foo"}
 // : 4 -> string "foox"
 // : 5 -> string "name"
 // settable expects the top of the stack to have the value,
 // then the field name. we're the other way around, so swap
 // them
 // stack: 1 -> table myCSV
 // : 2 -> string "x"
 // : 3 -> table {name="foo"}
 // : 4 -> string "foox" -- field value
 // : 5 -> string "name" -- field name
 lua_insert(L, -2);
 printf("silly: field stack is '%s'\n", luaL_checkstring(L, -1));
 printf("silly: stack is '%s'\n", luaL_checkstring(L, -2));
 // stack: 1 -> table myCSV
 // : 2 -> string "x"
 // : 3 -> table {name="foo"}
 // : 4 -> string "name" -- field name
 // : 5 -> string "foox" -- field value
 // now call settable to update the table on the stack
 lua_settable(L, 3);
 // stack: 1 -> table myCSV
 // : 2 -> string "x"
 // : 3 -> table {name="foox"}
 // get field value from the table
 lua_pushstring(L, key);
 // stack: 1 -> table myCSV
 // : 2 -> string "x"
 // : 3 -> table {name="foox"}
 // : 4 -> string "name"
 lua_gettable(L, 3);
 // stack: 1 -> table myCSV
 // : 2 -> string "x"
 // : 3 -> table {name="foox"}
 // : 4 -> table.foo which is string "foo"
 // confirm that we have a value for that field
 printf("silly: not of stack is '%s'\n", luaL_checkstring(L, -1));
 // get rid of the value from the stack
 // stack: 1 -> table myCSV
 // : 2 -> string "x"
 // : 3 -> table {name="foox"}
 // : 4 -> string "foox"
 lua_pop(L, 1);
 // stack: 1 -> table myCSV
 // : 2 -> string "x"
 // : 3 -> table {name="foox"}
 // check to see if the table has a field "type"
 key = "type";
 lua_pushstring(L, key);
 // stack: 1 -> table myCSV
 // : 2 -> string "x"
 // : 3 -> table {name="foox"}
 // : 4 -> string "type"
 lua_gettable(L, 3);
 // stack: 1 -> table myCSV
 // : 2 -> string "x"
 // : 3 -> table {name="foox"}
 // : 4 -> table.type which is nil
 if (lua_isnil(L, -1)) {
 // no value, so provide a default value for the type field in the table
 // stack: 1 -> table myCSV
 // : 2 -> string "x"
 // : 3 -> table {name="foox"}
 // : 4 -> nil
 // get rid of that value since we won't use it
 lua_pop(L, 1);
 // stack: 1 -> table myCSV
 // : 2 -> string "x"
 // : 3 -> table {name="foox"}
 // push the field name to update
 lua_pushstring(L, key);
 // stack: 1 -> table myCSV
 // : 2 -> string "x"
 // : 3 -> table {name="foox"}
 // : 4 -> string "type"
 // push the default value
 lua_pushstring(L, "default");
 // stack: 1 -> table myCSV
 // : 2 -> string "x"
 // : 3 -> table {name="foox"}
 // : 4 -> string "type"
 // : 5 -> string "default"
 // call settable to update the table on the stack
 lua_settable(L, 3);
 // stack: 1 -> table myCSV
 // : 2 -> string "x"
 // : 3 -> table {name="foox", type="default"}
 }
 return 0;
}

AltStyle によって変換されたページ (->オリジナル) /