mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
this_environment is now live
This commit is contained in:
parent
c7237806ef
commit
58003669fb
|
@ -10,12 +10,14 @@ Browse the various function and classes :doc:`Sol<../index>` utilizes to make yo
|
|||
:maxdepth: 2
|
||||
|
||||
state
|
||||
this_state
|
||||
reference
|
||||
stack_reference
|
||||
make_reference
|
||||
table
|
||||
userdata
|
||||
environment
|
||||
this_environment
|
||||
proxy
|
||||
containers
|
||||
nested
|
||||
|
@ -32,7 +34,6 @@ Browse the various function and classes :doc:`Sol<../index>` utilizes to make yo
|
|||
object
|
||||
thread
|
||||
optional
|
||||
this_state
|
||||
variadic_args
|
||||
as_args
|
||||
overload
|
||||
|
|
|
@ -175,7 +175,7 @@ This is an SFINAE-friendly struct that is meant to expose static function ``get`
|
|||
}
|
||||
};
|
||||
|
||||
This is an SFINAE-friendly struct that is meant to expose static function ``push`` that returns the number of things pushed onto the stack. The default implementation assumes ``T`` is a usertype and pushes a userdata into Lua with a :ref:`usertype_traits\<T><usertype-traits>` metatable associated with it. There are implementations for pushing numbers (``std::is_floating``, ``std::is_integral``-matching types), getting ``std::string`` and ``const char*``, getting raw userdata with :doc:`userdata<types>` and raw upvalues with :doc:`upvalue<types>`, getting raw `lua_CFunction`_ s, and finally pulling out Lua functions into ``sol::function``. It is also defined for anything that derives from :doc:`sol::reference<reference>`. It also has a special implementation for the 2 standard library smart pointers (see :doc:`usertype memory<usertype_memory>`).
|
||||
This is an SFINAE-friendly struct that is meant to expose static function ``push`` that returns the number of things pushed onto the stack. The default implementation assumes ``T`` is a usertype and pushes a userdata into Lua with a class-specific, state-wide metatable associated with it. There are implementations for pushing numbers (``std::is_floating``, ``std::is_integral``-matching types), getting ``std::string`` and ``const char*``, getting raw userdata with :doc:`userdata<types>` and raw upvalues with :doc:`upvalue<types>`, getting raw `lua_CFunction`_ s, and finally pulling out Lua functions into ``sol::function``. It is also defined for anything that derives from :doc:`sol::reference<reference>`. It also has a special implementation for the 2 standard library smart pointers (see :doc:`usertype memory<usertype_memory>`).
|
||||
|
||||
.. code-block:: cpp
|
||||
:caption: struct: checker
|
||||
|
|
|
@ -93,7 +93,7 @@ To handle errors when using the second overload, provide a callable function/obj
|
|||
});
|
||||
}
|
||||
|
||||
You can also pass a :doc:`sol::environment<environment>` to ``script``/``script_file`` to have the script have sandboxed / contained in a way inside of a state. This is useful for runnig multiple different "perspectives" or "views" on the same state. See the ``sol:
|
||||
You can also pass a :doc:`sol::environment<environment>` to ``script``/``script_file`` to have the script have sandboxed / contained in a way inside of a state. This is useful for runnig multiple different "perspectives" or "views" on the same state, and even has fallback support. See the :doc:`sol::environment<environment>` documentation for more details.
|
||||
|
||||
.. code-block:: cpp
|
||||
:caption: function: require / require_file
|
||||
|
|
44
docs/source/api/this_environment.rst
Normal file
44
docs/source/api/this_environment.rst
Normal file
|
@ -0,0 +1,44 @@
|
|||
this_environment
|
||||
================
|
||||
retrieving the environment of the calling function
|
||||
--------------------------------------------------
|
||||
|
||||
Sometimes in C++ it's useful to know where a Lua call is coming from and what :doc:`environment<environment>` it is from. The former is covered by Lua's Debug API, which is extensive and is not fully wrapped up by sol2. But, sol2 covers the latter in letting you get the environment of the calling script / function, if it has one. ``sol::this_environment`` is a *transparent argument* and does not need to be passed in Lua scripts or provided when using :doc:`sol::function<function>`, similar to :doc:`sol::this_state<this_state>`:
|
||||
|
||||
.. code-block:: cpp
|
||||
:linenos:
|
||||
|
||||
#define SOL_CHECK_ARGUMENTS
|
||||
#include <sol.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
||||
void env_check(sol::this_state ts, int x, sol::this_environment te) {
|
||||
std::cout << "In C++, 'int x' is in the second position, and its value is: " << x << std::endl;
|
||||
if (!te) {
|
||||
std::cout << "function does not have an environment: exiting function early" << std::endl;
|
||||
return;
|
||||
}
|
||||
sol::environment& env = te;
|
||||
sol::state_view lua = ts;
|
||||
sol::environment freshenv = lua["freshenv"];
|
||||
bool is_same_env = freshenv == env;
|
||||
std::cout << "env == freshenv : " << is_same_env << std::endl;
|
||||
}
|
||||
|
||||
int main() {
|
||||
sol::state lua;
|
||||
sol::environment freshenv(lua, sol::create, lua.globals());
|
||||
lua["freshenv"] = freshenv;
|
||||
|
||||
lua.set_function("f", env_check);
|
||||
lua.script("f(25)", freshenv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Also see `this example`_ for more details.
|
||||
|
||||
.. _this example: https://github.com/ThePhD/sol2/blob/develop/examples/environment_snooping.cpp
|
|
@ -5,14 +5,14 @@ usertype memory
|
|||
|
||||
Sol does not take ownership of raw pointers, returned from functions or set through the ``set`` functions. Return a value, a ``std::unique_ptr``, a ``std::shared_ptr`` of some kind, or hook up the :doc:`unique usertypes traits<unique_usertype_traits>` to work for some specific handle structure you use (AKA, for ``boost::shared_ptr``).
|
||||
|
||||
The userdata generated by Sol has a specific layout, depending on how Sol recognizes userdata passed into it. All of the referred to metatable names are generated from :ref:`usertype_traits\<T><usertype-traits>`. Note that we use 1 metatable per the 3 styles listed below, plus 1 additional metatable that is used for the actual table that you bind with the name when calling ``table::new/set_(simple_)usertype``.
|
||||
The userdata generated by Sol has a specific layout, depending on how Sol recognizes userdata passed into it. All of the referred to metatable names are generated from the name of the class itself. Note that we use 1 metatable per the 3 styles listed below, plus 1 additional metatable that is used for the actual table that you bind with the name when calling ``table::new/set_(simple_)usertype``.
|
||||
|
||||
In general, we always insert a T* in the first `sizeof(T*)` bytes, so the any framework that pulls out those first bytes expecting a pointer will work. The rest of the data has some different alignments and contents based on what it's used for and how it's used.
|
||||
|
||||
For ``T``
|
||||
---------
|
||||
|
||||
These are classified with the metatable name from :ref:`usertype_traits\<T><usertype-traits>`.
|
||||
These are classified with a metatable name generally derived from the class name itself.
|
||||
|
||||
The data layout for references is as follows::
|
||||
|
||||
|
|
|
@ -4,13 +4,24 @@
|
|||
#include <cassert>
|
||||
#include <iostream>
|
||||
|
||||
// Simple sol2 version of the below
|
||||
void simple(sol::this_state ts, sol::this_environment te) {
|
||||
sol::state_view lua = ts;
|
||||
if (te) {
|
||||
sol::environment& env = te;
|
||||
sol::environment freshenv = lua["freshenv"];
|
||||
bool is_same_env = freshenv == env;
|
||||
std::cout << "this_environment -- env == freshenv : " << is_same_env << std::endl;
|
||||
}
|
||||
std::cout << "this_environment -- no environment present" << std::endl;
|
||||
}
|
||||
|
||||
// NOTE:
|
||||
// THIS IS A LOW-LEVEL EXAMPLE, using pieces of sol2
|
||||
// to facilitate better usage
|
||||
// If you need to do this often, you can copy this code and paste it in a utility function for yourself
|
||||
// so you can grab the environment whenever you need to
|
||||
|
||||
void some_function_called_by_sol2(sol::this_state ts) {
|
||||
// It is recommended you just do the simple version, as it is basically this code
|
||||
// but it is sometimes useful to show the hoops you need to jump through to use the Lua C API
|
||||
void complicated(sol::this_state ts) {
|
||||
lua_State* L = ts;
|
||||
|
||||
lua_Debug info;
|
||||
|
@ -30,14 +41,14 @@ void some_function_called_by_sol2(sol::this_state ts) {
|
|||
// the rest is for printing / debugging purposes
|
||||
if (lua_getinfo(L, "fnluS", &info) == 0) {
|
||||
// failure?
|
||||
std::cout << "error: unable to get stack information" << std::endl;
|
||||
std::cout << "manually -- error: unable to get stack information" << std::endl;
|
||||
lua_settop(L, pre_stack_size);
|
||||
return;
|
||||
}
|
||||
|
||||
// Okay, so all the calls worked.
|
||||
// Print out some information about this "level"
|
||||
std::cout << "[" << level << "] " << info.short_src << ":" << info.currentline
|
||||
std::cout << "manually -- [" << level << "] " << info.short_src << ":" << info.currentline
|
||||
<< " -- " << (info.name ? info.name : "<unknown>") << "[" << info.what << "]" << std::endl;
|
||||
|
||||
// Grab the function off the top of the stack
|
||||
|
@ -48,14 +59,14 @@ void some_function_called_by_sol2(sol::this_state ts) {
|
|||
// The environment can now be ripped out of the function
|
||||
sol::environment env(sol::env_key, f);
|
||||
if (!env.valid()) {
|
||||
std::cout << "error: no environment to get" << std::endl;
|
||||
std::cout << "manually -- error: no environment to get" << std::endl;
|
||||
lua_settop(L, pre_stack_size);
|
||||
return;
|
||||
}
|
||||
sol::state_view lua(L);
|
||||
sol::environment freshenv = lua["freshenv"];
|
||||
bool is_same_env = freshenv == env;
|
||||
std::cout << "env == freshenv : " << is_same_env << std::endl;
|
||||
std::cout << "manually -- env == freshenv : " << is_same_env << std::endl;
|
||||
}
|
||||
|
||||
int main() {
|
||||
|
@ -64,9 +75,11 @@ int main() {
|
|||
|
||||
sol::environment freshenv(lua, sol::create, lua.globals());
|
||||
lua["freshenv"] = freshenv;
|
||||
lua.set_function("f", some_function_called_by_sol2);
|
||||
lua.set_function("f", simple);
|
||||
lua.set_function("g", complicated);
|
||||
|
||||
lua.script("f()", freshenv);
|
||||
lua.script("g()", freshenv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -597,9 +597,9 @@ namespace sol {
|
|||
return lua_call_wrapper<T, meta::unqualified_t<Fx>, is_index, is_variable, stack::stack_detail::default_check_arguments, boost>{}.call(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename T, bool is_index, bool is_variable, typename F>
|
||||
template <typename T, bool is_index, bool is_variable, typename F, int start = 1>
|
||||
inline int call_user(lua_State* L) {
|
||||
auto& fx = stack::get<user<F>>(L, upvalue_index(1));
|
||||
auto& fx = stack::get<user<F>>(L, upvalue_index(start));
|
||||
return call_wrapped<T, is_index, is_variable>(L, fx);
|
||||
}
|
||||
|
||||
|
|
|
@ -92,7 +92,8 @@ namespace sol {
|
|||
#else
|
||||
// Use upvalues as explained in Lua 5.2 and beyond's manual
|
||||
this->push();
|
||||
if (lua_setupvalue(L, -2, 1) == nullptr) {
|
||||
const char* name = lua_setupvalue(L, -2, 1);
|
||||
if (name == nullptr) {
|
||||
this->pop();
|
||||
}
|
||||
#endif
|
||||
|
@ -111,13 +112,74 @@ namespace sol {
|
|||
return basic_environment<E>(L, -1);
|
||||
}
|
||||
|
||||
struct this_environment {
|
||||
optional<environment> env;
|
||||
|
||||
this_environment() : env(nullopt) {}
|
||||
this_environment(sol::environment e) : env(std::move(e)) {}
|
||||
this_environment(const this_environment&) = default;
|
||||
this_environment(this_environment&&) = default;
|
||||
this_environment& operator=(const this_environment&) = default;
|
||||
this_environment& operator=(this_environment&&) = default;
|
||||
|
||||
explicit operator bool() const {
|
||||
return static_cast<bool>(env);
|
||||
}
|
||||
|
||||
operator optional<environment>& () {
|
||||
return env;
|
||||
}
|
||||
|
||||
operator const optional<environment>& () const {
|
||||
return env;
|
||||
}
|
||||
|
||||
operator environment& () {
|
||||
return env.value();
|
||||
}
|
||||
|
||||
operator const environment& () const {
|
||||
return env.value();
|
||||
}
|
||||
};
|
||||
|
||||
namespace stack {
|
||||
template <>
|
||||
struct getter<env_t> {
|
||||
static environment get(lua_State* L, int index = -1) {
|
||||
static environment get(lua_State* L, int index, record& tracking) {
|
||||
tracking.use(1);
|
||||
return get_environment(stack_reference(L, raw_index(index)));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct getter<this_environment> {
|
||||
static this_environment get(lua_State* L, int index, record& tracking) {
|
||||
tracking.use(0);
|
||||
lua_Debug info;
|
||||
// Level 0 means current function (this C function, which may or may not be useful for us?)
|
||||
// Level 1 means next call frame up the stack. (Can be nothing if function called directly from C++ with lua_p/call)
|
||||
int pre_stack_size = lua_gettop(L);
|
||||
if (lua_getstack(L, 1, &info) != 1) {
|
||||
if (lua_getstack(L, 0, &info) != 1) {
|
||||
lua_settop(L, pre_stack_size);
|
||||
return this_environment();
|
||||
}
|
||||
}
|
||||
if (lua_getinfo(L, "f", &info) == 0) {
|
||||
lua_settop(L, pre_stack_size);
|
||||
return this_environment();
|
||||
}
|
||||
|
||||
sol::stack_reference f(L, -1);
|
||||
sol::environment env(sol::env_key, f);
|
||||
if (!env.valid()) {
|
||||
lua_settop(L, pre_stack_size);
|
||||
return this_environment();
|
||||
}
|
||||
return this_environment(std::move(env));
|
||||
}
|
||||
};
|
||||
} // stack
|
||||
} // sol
|
||||
|
||||
|
|
|
@ -82,7 +82,9 @@ namespace sol {
|
|||
auto userptr = detail::ptr(std::forward<T>(obj), std::forward<Args>(args)...);
|
||||
lua_CFunction freefunc = &function_detail::upvalue_member_variable<std::decay_t<decltype(*userptr)>, meta::unqualified_t<Fx>>::call;
|
||||
|
||||
int upvalues = stack::stack_detail::push_as_upvalues(L, memfxptr);
|
||||
int upvalues = 0;
|
||||
upvalues += stack::push(L, nullptr);
|
||||
upvalues += stack::stack_detail::push_as_upvalues(L, memfxptr);
|
||||
upvalues += stack::push(L, lightuserdata_value(static_cast<void*>(userptr)));
|
||||
stack::push(L, c_closure(freefunc, upvalues));
|
||||
}
|
||||
|
@ -101,7 +103,9 @@ namespace sol {
|
|||
template <typename Fx, typename C>
|
||||
static void select_member_variable(std::true_type, lua_State* L, Fx&& fx, function_detail::class_indicator<C>) {
|
||||
lua_CFunction freefunc = &function_detail::upvalue_this_member_variable<C, Fx>::call;
|
||||
int upvalues = stack::stack_detail::push_as_upvalues(L, fx);
|
||||
int upvalues = 0;
|
||||
upvalues += stack::push(L, nullptr);
|
||||
upvalues += stack::stack_detail::push_as_upvalues(L, fx);
|
||||
stack::push(L, c_closure(freefunc, upvalues));
|
||||
}
|
||||
|
||||
|
@ -109,7 +113,9 @@ namespace sol {
|
|||
static void select_member_variable(std::true_type, lua_State* L, Fx&& fx) {
|
||||
typedef typename meta::bind_traits<meta::unqualified_t<Fx>>::object_type C;
|
||||
lua_CFunction freefunc = &function_detail::upvalue_this_member_variable<C, Fx>::call;
|
||||
int upvalues = stack::stack_detail::push_as_upvalues(L, fx);
|
||||
int upvalues = 0;
|
||||
upvalues += stack::push(L, nullptr);
|
||||
upvalues += stack::stack_detail::push_as_upvalues(L, fx);
|
||||
stack::push(L, c_closure(freefunc, upvalues));
|
||||
}
|
||||
|
||||
|
@ -127,7 +133,9 @@ namespace sol {
|
|||
auto userptr = detail::ptr(std::forward<T>(obj), std::forward<Args>(args)...);
|
||||
lua_CFunction freefunc = &function_detail::upvalue_member_function<std::decay_t<decltype(*userptr)>, meta::unqualified_t<Fx>>::call;
|
||||
|
||||
int upvalues = stack::stack_detail::push_as_upvalues(L, memfxptr);
|
||||
int upvalues = 0;
|
||||
upvalues += stack::push(L, nullptr);
|
||||
upvalues += stack::stack_detail::push_as_upvalues(L, memfxptr);
|
||||
upvalues += stack::push(L, lightuserdata_value(static_cast<void*>(userptr)));
|
||||
stack::push(L, c_closure(freefunc, upvalues));
|
||||
}
|
||||
|
@ -146,7 +154,9 @@ namespace sol {
|
|||
template <typename Fx, typename C>
|
||||
static void select_member_function(std::true_type, lua_State* L, Fx&& fx, function_detail::class_indicator<C>) {
|
||||
lua_CFunction freefunc = &function_detail::upvalue_this_member_function<C, Fx>::call;
|
||||
int upvalues = stack::stack_detail::push_as_upvalues(L, fx);
|
||||
int upvalues = 0;
|
||||
upvalues += stack::push(L, nullptr);
|
||||
upvalues += stack::stack_detail::push_as_upvalues(L, fx);
|
||||
stack::push(L, c_closure(freefunc, upvalues));
|
||||
}
|
||||
|
||||
|
@ -154,7 +164,9 @@ namespace sol {
|
|||
static void select_member_function(std::true_type, lua_State* L, Fx&& fx) {
|
||||
typedef typename meta::bind_traits<meta::unqualified_t<Fx>>::object_type C;
|
||||
lua_CFunction freefunc = &function_detail::upvalue_this_member_function<C, Fx>::call;
|
||||
int upvalues = stack::stack_detail::push_as_upvalues(L, fx);
|
||||
int upvalues = 0;
|
||||
upvalues += stack::push(L, nullptr);
|
||||
upvalues += stack::stack_detail::push_as_upvalues(L, fx);
|
||||
stack::push(L, c_closure(freefunc, upvalues));
|
||||
}
|
||||
|
||||
|
@ -168,7 +180,9 @@ namespace sol {
|
|||
std::decay_t<Fx> target(std::forward<Fx>(fx), std::forward<Args>(args)...);
|
||||
lua_CFunction freefunc = &function_detail::upvalue_free_function<Fx>::call;
|
||||
|
||||
int upvalues = stack::stack_detail::push_as_upvalues(L, target);
|
||||
int upvalues = 0;
|
||||
upvalues += stack::push(L, nullptr);
|
||||
upvalues += stack::stack_detail::push_as_upvalues(L, target);
|
||||
stack::push(L, c_closure(freefunc, upvalues));
|
||||
}
|
||||
|
||||
|
@ -183,10 +197,12 @@ namespace sol {
|
|||
|
||||
template <typename Fx, typename... Args>
|
||||
static void set_fx(lua_State* L, Args&&... args) {
|
||||
lua_CFunction freefunc = function_detail::call<meta::unqualified_t<Fx>>;
|
||||
lua_CFunction freefunc = function_detail::call<meta::unqualified_t<Fx>, 2>;
|
||||
|
||||
stack::push<user<Fx>>(L, std::forward<Args>(args)...);
|
||||
stack::push(L, c_closure(freefunc, 1));
|
||||
int upvalues = 0;
|
||||
upvalues += stack::push(L, nullptr);
|
||||
upvalues += stack::push<user<Fx>>(L, std::forward<Args>(args)...);
|
||||
stack::push(L, c_closure(freefunc, upvalues));
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
|
@ -254,15 +270,19 @@ namespace sol {
|
|||
template <typename T>
|
||||
struct pusher<protect_t<T>> {
|
||||
static int push(lua_State* L, protect_t<T>&& pw) {
|
||||
lua_CFunction cf = call_detail::call_user<void, false, false, protect_t<T>>;
|
||||
int closures = stack::push<user<protect_t<T>>>(L, std::move(pw.value));
|
||||
return stack::push(L, c_closure(cf, closures));
|
||||
lua_CFunction cf = call_detail::call_user<void, false, false, protect_t<T>, 2>;
|
||||
int upvalues = 0;
|
||||
upvalues += stack::push(L, nullptr);
|
||||
upvalues += stack::push<user<protect_t<T>>>(L, std::move(pw.value));
|
||||
return stack::push(L, c_closure(cf, upvalues));
|
||||
}
|
||||
|
||||
static int push(lua_State* L, const protect_t<T>& pw) {
|
||||
lua_CFunction cf = call_detail::call_user<void, false, false, protect_t<T>>;
|
||||
int closures = stack::push<user<protect_t<T>>>(L, pw.value);
|
||||
return stack::push(L, c_closure(cf, closures));
|
||||
lua_CFunction cf = call_detail::call_user<void, false, false, protect_t<T>, 2>;
|
||||
int upvalues = 0;
|
||||
upvalues += stack::push(L, nullptr);
|
||||
upvalues += stack::push<user<protect_t<T>>>(L, pw.value);
|
||||
return stack::push(L, c_closure(cf, upvalues));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -357,9 +377,11 @@ namespace sol {
|
|||
struct pusher<detail::tagged<T, constructor_wrapper<Fxs...>>> {
|
||||
template <typename C>
|
||||
static int push(lua_State* L, C&& c) {
|
||||
lua_CFunction cf = call_detail::call_user<T, false, false, constructor_wrapper<Fxs...>>;
|
||||
int closures = stack::push<user<constructor_wrapper<Fxs...>>>(L, std::forward<C>(c));
|
||||
return stack::push(L, c_closure(cf, closures));
|
||||
lua_CFunction cf = call_detail::call_user<T, false, false, constructor_wrapper<Fxs...>, 2>;
|
||||
int upvalues = 0;
|
||||
upvalues += stack::push(L, nullptr);
|
||||
upvalues += stack::push<user<constructor_wrapper<Fxs...>>>(L, std::forward<C>(c));
|
||||
return stack::push(L, c_closure(cf, upvalues));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -374,9 +396,11 @@ namespace sol {
|
|||
template <typename T, typename Fx>
|
||||
struct pusher<detail::tagged<T, destructor_wrapper<Fx>>> {
|
||||
static int push(lua_State* L, destructor_wrapper<Fx> c) {
|
||||
lua_CFunction cf = call_detail::call_user<T, false, false, destructor_wrapper<Fx>>;
|
||||
int closures = stack::push<user<T>>(L, std::move(c));
|
||||
return stack::push(L, c_closure(cf, closures));
|
||||
lua_CFunction cf = call_detail::call_user<T, false, false, destructor_wrapper<Fx>, 2>;
|
||||
int upvalues = 0;
|
||||
upvalues += stack::push(L, nullptr);
|
||||
upvalues += stack::push<user<T>>(L, std::move(c));
|
||||
return stack::push(L, c_closure(cf, upvalues));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -28,9 +28,9 @@
|
|||
|
||||
namespace sol {
|
||||
namespace function_detail {
|
||||
template <typename Fx>
|
||||
template <typename Fx, int start = 1>
|
||||
inline int call(lua_State* L) {
|
||||
Fx& fx = stack::get<user<Fx>>(L, upvalue_index(1));
|
||||
Fx& fx = stack::get<user<Fx>>(L, upvalue_index(start));
|
||||
return fx(L);
|
||||
}
|
||||
} // function_detail
|
||||
|
|
|
@ -57,7 +57,7 @@ namespace sol {
|
|||
// idx n + 1: is the object's void pointer
|
||||
// We don't need to store the size, because the other side is templated
|
||||
// with the same member function pointer type
|
||||
auto memberdata = stack::stack_detail::get_as_upvalues<function_type>(L, 1);
|
||||
auto memberdata = stack::stack_detail::get_as_upvalues<function_type>(L);
|
||||
auto objdata = stack::stack_detail::get_as_upvalues<T*>(L, memberdata.second);
|
||||
function_type& memfx = memberdata.first;
|
||||
auto& item = *objdata.first;
|
||||
|
@ -84,7 +84,7 @@ namespace sol {
|
|||
// idx n + 1: is the object's void pointer
|
||||
// We don't need to store the size, because the other side is templated
|
||||
// with the same member function pointer type
|
||||
auto memberdata = stack::stack_detail::get_as_upvalues<function_type>(L, 1);
|
||||
auto memberdata = stack::stack_detail::get_as_upvalues<function_type>(L);
|
||||
auto objdata = stack::stack_detail::get_as_upvalues<T*>(L, memberdata.second);
|
||||
auto& mem = *objdata.first;
|
||||
function_type& var = memberdata.first;
|
||||
|
@ -115,7 +115,7 @@ namespace sol {
|
|||
static int real_call(lua_State* L) {
|
||||
// Layout:
|
||||
// idx 1...n: verbatim data of member variable pointer
|
||||
auto memberdata = stack::stack_detail::get_as_upvalues<function_type>(L, 1);
|
||||
auto memberdata = stack::stack_detail::get_as_upvalues<function_type>(L);
|
||||
function_type& memfx = memberdata.first;
|
||||
return call_detail::call_wrapped<T, false, false>(L, memfx);
|
||||
}
|
||||
|
@ -137,7 +137,7 @@ namespace sol {
|
|||
static int real_call(lua_State* L) {
|
||||
// Layout:
|
||||
// idx 1...n: verbatim data of member variable pointer
|
||||
auto memberdata = stack::stack_detail::get_as_upvalues<function_type>(L, 1);
|
||||
auto memberdata = stack::stack_detail::get_as_upvalues<function_type>(L);
|
||||
function_type& var = memberdata.first;
|
||||
switch (lua_gettop(L)) {
|
||||
case 1:
|
||||
|
|
|
@ -56,7 +56,7 @@ namespace sol {
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
inline std::pair<T, int> get_as_upvalues(lua_State* L, int index = 1) {
|
||||
inline std::pair<T, int> get_as_upvalues(lua_State* L, int index = 2) {
|
||||
const static std::size_t data_t_count = (sizeof(T) + (sizeof(void*) - 1)) / sizeof(void*);
|
||||
typedef std::array<void*, data_t_count> data_t;
|
||||
data_t voiddata{ {} };
|
||||
|
|
|
@ -136,6 +136,15 @@ namespace sol {
|
|||
}
|
||||
};
|
||||
|
||||
template <typename C>
|
||||
struct checker<this_environment, type::poly, C> {
|
||||
template <typename Handler>
|
||||
static bool check(lua_State*, int, Handler&&, record& tracking) {
|
||||
tracking.use(0);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename C>
|
||||
struct checker<variadic_args, type::poly, C> {
|
||||
template <typename Handler>
|
||||
|
|
|
@ -633,6 +633,7 @@ namespace sol {
|
|||
class thread;
|
||||
struct variadic_args;
|
||||
struct this_state;
|
||||
struct this_environment;
|
||||
|
||||
namespace detail {
|
||||
template <typename T, typename = void>
|
||||
|
@ -785,6 +786,9 @@ namespace sol {
|
|||
template <>
|
||||
struct lua_type_of<this_state> : std::integral_constant<type, type::poly> {};
|
||||
|
||||
template <>
|
||||
struct lua_type_of<this_environment> : std::integral_constant<type, type::poly> {};
|
||||
|
||||
template <>
|
||||
struct lua_type_of<type> : std::integral_constant<type, type::poly> {};
|
||||
|
||||
|
@ -901,6 +905,9 @@ namespace sol {
|
|||
template <>
|
||||
struct is_transparent_argument<this_state> : std::true_type {};
|
||||
|
||||
template <>
|
||||
struct is_transparent_argument<this_environment> : std::true_type {};
|
||||
|
||||
template <>
|
||||
struct is_transparent_argument<variadic_args> : std::true_type {};
|
||||
|
||||
|
|
|
@ -201,3 +201,35 @@ TEST_CASE("environments/functions", "see if environments on functions are workin
|
|||
REQUIRE(!gtest.valid());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("environments/this_environment", "test various situations of pulling out an environment") {
|
||||
static std::string code = "return f(10)";
|
||||
|
||||
sol::state lua;
|
||||
|
||||
lua["f"] = [](sol::this_environment te, int x) {
|
||||
if (te) {
|
||||
sol::environment& env = te;
|
||||
return x + static_cast<int>(env["x"]);
|
||||
}
|
||||
return x;
|
||||
};
|
||||
|
||||
sol::environment e(lua, sol::create, lua.globals());
|
||||
e["x"] = 20;
|
||||
SECTION("from Lua script") {
|
||||
int value = lua.script(code, e);
|
||||
REQUIRE(value == 30);
|
||||
}
|
||||
SECTION("from C++") {
|
||||
sol::function f = lua["f"];
|
||||
e.set_on(f);
|
||||
int value = f(10);
|
||||
REQUIRE(value == 30);
|
||||
}
|
||||
SECTION("from C++, with no env") {
|
||||
sol::function f = lua["f"];
|
||||
int value = f(10);
|
||||
REQUIRE(value == 10);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user