Sol2: Passing sol::table between Lua scripts and C++

Created on 23 Mar 2017  路  1Comment  路  Source: ThePhD/sol2

I am having an issue passing sol::table around from Lua, to C++, and then back to Lua.

Here is a minimal example that reproduces the issue I am facing:

The C++ code:

#include <iostream>
#include <string>

#include <sol2/sol.hpp>

void test_function(sol::table properties) {
    std::cout << "Inside: test_function" << std::endl;

    std::string text = properties["text"];
    std::cout << "The text is: " << text << std::endl;
    std::cout << "The number is: " << static_cast<int>(properties["number"]) << std::endl;

    sol::state lua;
    lua.open_libraries(sol::lib::base, sol::lib::math, sol::lib::string, sol::lib::io);
    lua.script_file("test_script.lua");

    sol::function second_func = lua["second_func"];
    second_func(properties);
}

int main(int argc, char** argv) {
    sol::state lua;
    lua.open_libraries(sol::lib::base, sol::lib::math, sol::lib::string, sol::lib::io);

    lua.set_function("test_function", test_function);
    lua.script_file("test_script.lua");

    sol::function first_func = lua["first_func"];
    first_func();

    return 0;
}

The Lua script:

function first_func()
    print('Inside: first_func')

    properties = {}
    properties['text'] = 'blarg'
    properties['number'] = 8

    test_function(properties)
end

function second_func(properties)
    print('Inside: second_func')

    print('The text is:', properties['text'])
    print('The number is:', properties['number'])
end

Here is the output when I run the program:

> ./sol_test 
Inside: first_func
Inside: test_function
The text is: blarg
The number is: 8
Inside: second_func
terminate called after throwing an instance of 'sol::error'
  what():  lua: error: lua: error: test_script.lua:14: attempt to index a nil value (local 'properties')
Aborted

Is this expected behavior? I would think the sol::table should be copied from Lua to C++, and then be copied back into Lua from C++.

Let me know if you need more information to debug this. Thanks. :slightly_smiling_face:

Docs.Are Good Help.Desk

Most helpful comment

The first sol::table comes from a different Lua state. You can't transfer tables between states. You have 2 lua states in your code: one in the main, one in the first_func. Each sol::state is its own lua_State*, and each contains its own references and memory that cannot be mixed unless you specifically invoke the Lua C API calls to switch between states / threads.

If you need to access the same Lua state, please use sol::this_state: docs here. Here's your example, using it:

````cpp

include

include

void test_function(sol::table properties, sol::this_state ts) {
std::cout << "Inside: test_function" << std::endl;

// get a view into a previously-made lua state
sol::state_view lua = ts;

// now this will work
// because you're getting the same table here
// and not some weird table "properties" that doesn't actually exist
// in some new lua state you're freshly allocating
sol::function second_func = lua["second_func"];
second_func(properties);

}

int main(int argc, char** argv) {
sol::state lua;
lua.open_libraries(sol::lib::base, sol::lib::math, sol::lib::string, sol::lib::io);

lua.set_function("test_function", test_function);
lua.script_file("test_script.lua");

sol::function first_func = lua["first_func"];
first_func();

return 0;

}
````

And it works exactly as you'd expect.

>All comments

The first sol::table comes from a different Lua state. You can't transfer tables between states. You have 2 lua states in your code: one in the main, one in the first_func. Each sol::state is its own lua_State*, and each contains its own references and memory that cannot be mixed unless you specifically invoke the Lua C API calls to switch between states / threads.

If you need to access the same Lua state, please use sol::this_state: docs here. Here's your example, using it:

````cpp

include

include

void test_function(sol::table properties, sol::this_state ts) {
std::cout << "Inside: test_function" << std::endl;

// get a view into a previously-made lua state
sol::state_view lua = ts;

// now this will work
// because you're getting the same table here
// and not some weird table "properties" that doesn't actually exist
// in some new lua state you're freshly allocating
sol::function second_func = lua["second_func"];
second_func(properties);

}

int main(int argc, char** argv) {
sol::state lua;
lua.open_libraries(sol::lib::base, sol::lib::math, sol::lib::string, sol::lib::io);

lua.set_function("test_function", test_function);
lua.script_file("test_script.lua");

sol::function first_func = lua["first_func"];
first_func();

return 0;

}
````

And it works exactly as you'd expect.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

hmenke picture hmenke  路  6Comments

TheMaverickProgrammer picture TheMaverickProgrammer  路  6Comments

Rochet2 picture Rochet2  路  7Comments

spin-scenario picture spin-scenario  路  8Comments

shohnwal picture shohnwal  路  4Comments