environment

encapsulation table for script sandboxing

environment
class environment : public table;

template <typename T>
void set_environment( const environment& env, const T& target );
template <typename E = reference, typename T>
basic_environment<E> get_environment( const T& target );

This type is passed to sol::state(_view)::script/do_x to provide an environment where local variables that are set and get retrieve. It is just a plain table, and all the same operations from table still apply. This is important because it allows you to do things like set the table’s metatable (using sol::metatable_key for instance) and having its __index entry point to the global table, meaning you can get – but not set – variables from a Global environment, for example.

There are many more uses, including storing state or special dependent variables in an environment that you pre-create using regular table opertions, and then changing at-will:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#define SOL_ALL_SAFETIES_ON 1
#include <sol/sol.hpp>

int main (int, char*[]) {
	sol::state lua;
	lua.open_libraries();
	sol::environment my_env(lua, sol::create);
	// set value, and we need to explicitly allow for 
	// access to "print", since a new environment hides 
	// everything that's not defined inside of it
	// NOTE: hiding also hides library functions (!!)
	// BE WARNED
	my_env["var"] = 50;
	my_env["print"] = lua["print"];

	sol::environment my_other_env(lua, sol::create, lua.globals());
	// do not need to explicitly allow access to "print",
	// since we used the "Set a fallback" version 
	// of the sol::environment constructor
	my_other_env["var"] = 443;

	// output: 50
	lua.script("print(var)", my_env);

	// output: 443
	lua.script("print(var)", my_other_env);

	return 0;
}

Also note that sol::environment derives from sol::table, which also derives from sol::reference: in other words, copying one sol::environment value to another sol::environment value does not deep-copy the table, just creates a new reference pointing to the same lua object.

sol::environment objects can be used with script calls, and it can also be set on functions. It can even be applied to threads.

You can set the environment using sol::set_environment( my_env, some_reference ); or my_env.set_on( some_reference );.

free functions

function: set_environment
template <typename T>
void set_environment( const environment& env, const T& target );

See environment::set_on.

function: get_environment
template <typename E = reference, typename T>
basic_environment<E> get_environment( const T& target );

This function retrieves the environment from the target object. If it does not have a valid environment, then the environment’s valid function will return false after creation. Every function (regular Lua function, executable script, and similar) has an environment, as well as userdata in certain versions of the Lua runtime.

members

constructor: environment
environment(lua_State* L, sol::new_table nt);
environment(lua_State* L, sol::new_table nt, const sol::reference& fallback);
environment(sol::env_key_t, const sol::reference& object_that_has_environment);
environment(sol::env_key_t, const sol::stack_reference& object_that_has_environment);

The ones from table are used here (of particular note is the ability to use sol::environment(my_lua_state, sol::create); to make a fresh, unnamed environment), plus the three unique constructors shown above.

The first constructor is generally used as sol::environment my_env(my_lua_state, sol::create, my_fallback_table);. The fallback table serves as the backup to lookup attempts on the environment table being created. It is achieved by simply creating a metatable for the sol::environment being created, and then doing env_metatable["__index"] = fallback;. You can achieve fancier effects by changing the metatable of the environment to your liking, by creating it in some fashion and then setting the metatable explicitly and populating it with data, particularly with sol::metatable_key.

The second and third unique constructors take a special empty type that serves as a key to trigger this constructor and serves no other purpose, sol::env_key_t. The shortcut value so you don’t have to create one is called sol::env_key. It is used like sol::environment my_env(sol::env_key, some_object);. It will extract the environment out of whatever the second argument is that may or may not have an environment. If it does not have an environment, the constructor will complete but the object will have env.valid() == false, since it will reference Lua’s nil.

function: set_on
template <typename T>
void set_on(const T& target);

This function applies the environment to the desired target. Not that lua 5.1 only tolerates the application of environments to userdata, threads and functions, while 5.2+ has different (more relaxed) rules. It is called by the free function sol::set_environment( env, target );.