2

My Code:

lua_State *L = luaL_newstate();
luaL_openlibs(L);
lua_settop(L, 0);
//Script A
luaL_dostring(L, "A = {} A.num = 3");
//Script B
luaL_dostring(L, "B = {} function B.update() return A.num * 2 end");
//Script C
luaL_dostring(L, "print(B.update())"); 
lua_close(L);

The Result: 6

However if I make the table A and B local like the following:

lua_State *L = luaL_newstate();
luaL_openlibs(L);
lua_settop(L, 0);
//Script A
luaL_dostring(L, "local A = {} A.num = 3");
//Script B
luaL_dostring(L, "local B = {} function B.update() return A.num * 2 end");
//Script C
luaL_dostring(L, "print(B.update())"); 
lua_close(L);

It doesn't output anything.

How to make the second code work and what is more recommended design between the two?

ADDITIONAL QUESTION: Is putting all functions and variables inside a uniquely named table per .lua file a common technique in Lua to avoid name collision between each files?

2
  • 1
    Local variables are not accessible from beyond their lexical scope. And their lexical scope is inside the chunk where they were defined. Each dostring introduces separate chunk. Commented Jul 17, 2018 at 11:42
  • Always check for errors! luaL_dostring(L, "print(B.update())"); in second example will fail with something like failed to index nil global "B" Commented Jul 18, 2018 at 15:56

2 Answers 2

5

Local variables are private to the scripts that define them. That is the whole point.

If you want to export something from a script, return it. Scripts that define libraries typically return a table. This is much more polite than polluting the global environment.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for your answer. Could you please show me an example by modifying my second example so it can print 6?
2

As Luiz Henrique already mentioned, local variables cannot be accessed outside their scope and it is impolite to pollute the global environment with hardcoded names.

Instead you could make use of the trick that I have presented already in this answer of mine to another question of yours. Use luaL_loadstring rather than luaL_dostring to load the script into a function and register this function as a field in package.preload. Then, inside of your chunks, you can easily require the preloaded modules into local variables.

#include <lua.hpp>

int main() {
    lua_State *L = luaL_newstate();
    luaL_openlibs(L);
    lua_settop(L, 0);

    lua_getglobal(L, "package");
    lua_getfield(L, -1, "preload");

    // Script A
    luaL_loadstring(L, "return { num = 3 }");
    lua_setfield(L, -2, "A");

    // Script B
    luaL_loadstring(L, "local A = require('A')\n"
                       "return { update = function() return A.num * 2 end }");
    lua_setfield(L, -2, "B");

    // Script C
    luaL_dostring(L, "local B = require('B')\n"
                     "print(B.update())");

    lua_close(L);
}

That should also answer your additional question: No, use modules as described above.

1 Comment

Thank you so much. This is great!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.