jiandingzhe
jiandingzhe

Reputation: 2121

Lua crashed when metatable __index pointing to a function and returned value is not used

I'm trying to use function as metatable __index to achieve more flexibiilty, but it crashed when the returned value is not assigned to some variable in Lua side.

This is the C++ part, it just creates a table variable whose __index is pointing to a C function, the function just returns a fixed number value:

int meta_index( lua_State* lua )
{
    juce::Logger::writeToLog( "meta_index with key " + juce::String( lua_tostring( lua, 2 ) ) );
    lua_pushnumber( lua, 123.456 );
    return 1;
}


int main()
{
    lua_State* lua = luaL_newstate();
    luaL_openlibs( lua );

    // create a table with __index slot
    lua_createtable( lua, 0, 0 );
    lua_pushstring( lua, "__index" );
    lua_pushcfunction( lua, meta_index );
    lua_settable( lua, -3 );
    lua_setglobal( lua, "test_meta" );

    // run lua code
    luaL_loadstring( lua, lua_src );
    lua_call( lua, 0, 0 );
    lua_close( lua );
}

And this is the Lua code that causes crash:

const char* lua_src =
    "a = {}\n"
    "setmetatable(a, test_meta)\n"
    "a.foo\n";

The code crashed before C function meta_index is actually called, and it claims a error message attempt to call a string value.

However, if I put the expression a.foo who triggers meta indexing on the right of assignment, the code finishes with no error and produces expected result:

const char* lua_src =
    "a = {}\n"
    "setmetatable(a, test_meta)\n"
    "bar = a.foo\n"
    "print(bar)\n";

It seems Lua treats the foo in a.foo and bar = a.foo as different things, what is the actual rule for it?

Upvotes: 2

Views: 187

Answers (1)

lhf
lhf

Reputation: 72312

The code below does not compile because expressions like a.foo are not statements in Lua:

a = {}
setmetatable(a, test_meta)
a.foo

The error message is

4: syntax error near <eof>

This string is left on the top of the stack after luaL_loadstring. Hence the error attempt to call a string value when you call lua_call.

Bottom line: always check the return code of luaL_loadstring and print any error messages.

Upvotes: 2

Related Questions