Zack Lee
Zack Lee

Reputation: 3044

How to share global variables between Lua scripts

I would like to know how to share global variables between Lua scripts.

I tried to do this myself using require but it doesn't work as I expected.

Here's my simple example code.

In test.lua

num = 2

In A.lua

require(`test`);
num = 5

In B.lua

require(`test`);
print(num);

And if I run A.lua first, then B.lua, I get the following result:

2

But I expect to get 5 because I modified the variable value to 2 in A.lua.

Is it possible to achieve what I want? (I would appreciate an example)

Upvotes: 5

Views: 10643

Answers (3)

Henri Menke
Henri Menke

Reputation: 10939

There is no dedicated function to require Lua modules from the C-API.[1] So I oriented myself on the function dolibrary in the Lua interpreter to implement require which simply calls the Lua require function from C.

N.B.: I don't recommend having modules communicate by sharing global variables, especially when the order of loading the modules matters as is the case here. Better provide methods A.update_num(old) and B.update_num(old) which take the old value of num as an argument and return the updated value.

#include <iostream>

#include <lua.hpp>

int require(lua_State *L, char const * modname) {
    int const size = lua_gettop(L);

    lua_getglobal(L, "require");
    lua_pushstring(L, modname);

    if (lua_pcall(L, 1, LUA_MULTRET, 0) != 0) {
        std::cerr << "lua:" << lua_tostring(L, 1) << '\n';
        lua_pop(L,1);
        return 0; // Failed, nothing should be on the stack
    }

    return lua_gettop(L) - size;
}

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

    require(L, "A");
    require(L, "B");

    lua_close(L);
}

With the scripts from your question in the same directory we get:

$ clang++ -Wall -Wextra -Wpedantic -I /usr/include/lua5.2/ test.cpp -llua5.2
$ ./a.out 
5

[1] There is lua_requiref to require Lua C modules from the C-API.

Upvotes: 1

Quirinux
Quirinux

Reputation: 346

a.lua

a = 5

b.lua

require('a')
a = 2

test.lua

require('b')
print(a)

You should get 2, because the require chain works from top-bottom, if you just run each file a time lua will execute just this little uniq execution, there is no persistency acros diferent executions, so you need to require as needed

Upvotes: 1

Felix
Felix

Reputation: 2386

What you are currently doing is the following:

lua A.lua
> lua process starts
> loading A.lua
> loading test.lua (because it is required by A.lua)
> set global "num" to value 2
> set global "num" to value 5
> lua process exits (A.lua finished)
lua B.lua
> lua process starts
> loading B.lua
> loading test.lua (because it is required by B.lua)
> set global "num" to value 2
> print global "num" (which was set to 2 by test.lua)
> lua process exits (B.lua finished)

To print the value 5 your scripts should look like this:

-- test.lua
num = 2

-- A.lua
require("test")
num = 5

-- B.lua
require("test")
require("A")
print(num)

which will result in:

lua B.lua
> lua process starts
> loading B.lua
> loading test.lua (because it is required by B.lua)
> set global "num" to value 2
> loading A.lua (because it is required by B.lua)
> skip loading test.lua (has already been loaded)
> set global "num" to value 5
> print global "num"
> lua process exits (B.lua finished)

EDIT: I see you're using the C Api of Lua and not a Lua binary to execute your scripts. Using the programming api you should be able the get your required result by executing A.lua and B.lua using the same lua-state (most commonly stored in the C-Variable "L").

Upvotes: 5

Related Questions