mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
add code to steal guts and grab stuff from other frameworks.
This commit is contained in:
parent
2b2c222bf0
commit
6d879f571a
|
@ -77,7 +77,7 @@ SpaceInEmptyParentheses: false
|
||||||
SpacesInAngles: false
|
SpacesInAngles: false
|
||||||
SpacesInParentheses: false
|
SpacesInParentheses: false
|
||||||
SpacesInSquareBrackets: false
|
SpacesInSquareBrackets: false
|
||||||
MaxEmptyLinesToKeep: 1
|
MaxEmptyLinesToKeep: 3
|
||||||
|
|
||||||
# OCD
|
# OCD
|
||||||
SortUsingDeclarations: true
|
SortUsingDeclarations: true
|
||||||
|
|
|
@ -235,7 +235,10 @@ This is an SFINAE-friendly struct that is meant to expose static function ``push
|
||||||
template <typename Handler>
|
template <typename Handler>
|
||||||
static bool check ( lua_State* L, int index, Handler&& handler, record& tracking ) {
|
static bool check ( lua_State* L, int index, Handler&& handler, record& tracking ) {
|
||||||
// if the object in the Lua stack at index is a T, return true
|
// if the object in the Lua stack at index is a T, return true
|
||||||
if ( ... ) return true;
|
if ( ... ) {
|
||||||
|
tracking.use(1); // or however many you use
|
||||||
|
return true;
|
||||||
|
}
|
||||||
// otherwise, call the handler function,
|
// otherwise, call the handler function,
|
||||||
// with the required 5 arguments, then return false
|
// with the required 5 arguments, then return false
|
||||||
//
|
//
|
||||||
|
@ -244,8 +247,57 @@ This is an SFINAE-friendly struct that is meant to expose static function ``push
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
This is an SFINAE-friendly struct that is meant to expose static function ``check`` that returns the number of things pushed onto the stack. The default implementation simply checks whether the expected type passed in through the template is equal to the type of the object at the specified index in the Lua stack. The default implementation for types which are considered ``userdata`` go through a myriad of checks to support checking if a type is *actually* of type ``T`` or if its the base class of what it actually stored as a userdata in that index. Down-casting from a base class to a more derived type is, unfortunately, impossible to do.
|
This is an SFINAE-friendly struct that is meant to expose static function ``check`` that returns whether or not a type at a given index is what its supposed to be. The default implementation simply checks whether the expected type passed in through the template is equal to the type of the object at the specified index in the Lua stack. The default implementation for types which are considered ``userdata`` go through a myriad of checks to support checking if a type is *actually* of type ``T`` or if its the base class of what it actually stored as a userdata in that index. Down-casting from a base class to a more derived type is, unfortunately, impossible to do.
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
:caption: struct: userdata_checker
|
||||||
|
:name: userdata_checker
|
||||||
|
|
||||||
|
template <typename T, typename = void>
|
||||||
|
struct userdata_checker {
|
||||||
|
template <typename Handler>
|
||||||
|
static bool check ( lua_State* L, int index, type indextype, Handler&& handler, record& tracking ) {
|
||||||
|
// implement custom checking here for a userdata:
|
||||||
|
// if it doesn't match, return "false" and regular
|
||||||
|
// sol userdata checks will kick in
|
||||||
|
return false;
|
||||||
|
// returning true will skip sol's
|
||||||
|
// default checks
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
This is an SFINAE-friendly struct that is meant to expose a function ``check=`` that returns ``true`` if a type meets some custom userdata specifiction, and ``false`` if it does not. The default implementation just returns ``false`` to let the original sol2 handlers take care of everything. If you want to implement your own usertype checking; e.g., for messing with ``toLua`` or ``OOLua`` or ``kaguya`` or some other libraries. Note that the library must have a with a :doc:`memory compatible layout<usertype_memory>` if you **want to specialize this checker method but not the subsequent getter method**. You can specialize it as shown in the `interop examples`_.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
You must turn it on with ``SOL_ENABLE_INTEROP``, as described in the :ref:`config and safety section<config>`.
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
:caption: struct: userdata_getter
|
||||||
|
:name: userdata_getter
|
||||||
|
|
||||||
|
template <typename T, typename = void>
|
||||||
|
struct userdata_getter {
|
||||||
|
static std::pair<bool, T*> get ( lua_State* L, int index, void* unadjusted_pointer, record& tracking ) {
|
||||||
|
// implement custom getting here for non-sol2 userdatas:
|
||||||
|
// if it doesn't match, return "false" and regular
|
||||||
|
// sol userdata checks will kick in
|
||||||
|
return { false, nullptr };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
This is an SFINAE-friendly struct that is meant to expose a function ``get`` that returns ``true`` and an adjusted pointer if a type meets some custom userdata specifiction (from, say, another library or an internal framework). The default implementation just returns ``{ false, nullptr }`` to let the original sol2 getter take care of everything. If you want to implement your own usertype getter; e.g., for messing with ``kaguya`` or some other libraries. You can specialize it as shown in the `interop examples`_.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
You do NOT need to use this method in particular if the :doc:`memory layout<usertype_memory>` is compatible. (For example, ``toLua`` stores userdata in a sol2-compatible way.)
|
||||||
|
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
You must turn it on with ``SOL_ENABLE_INTEROP``, as described in the :ref:`config and safety section<config>`.
|
||||||
|
|
||||||
|
|
||||||
.. _lua_CFunction: http://www.Lua.org/manual/5.3/manual.html#lua_CFunction
|
.. _lua_CFunction: http://www.Lua.org/manual/5.3/manual.html#lua_CFunction
|
||||||
.. _Lua stack works in general: https://www.lua.org/pil/24.2.html
|
.. _Lua stack works in general: https://www.lua.org/pil/24.2.html
|
||||||
.. _calling C functions works: https://www.lua.org/pil/26.html
|
.. _calling C functions works: https://www.lua.org/pil/26.html
|
||||||
|
.. _interop example: https://github.com/ThePhD/sol2/blob/develop/examples/interop
|
||||||
|
|
|
@ -13,6 +13,13 @@ Note that you can obtain safety with regards to functions you bind by using the
|
||||||
``SOL_USE_BOOST`` triggers the following change:
|
``SOL_USE_BOOST`` triggers the following change:
|
||||||
* Attempts to use ``boost::optional`` instead of sol's own ``optional``
|
* Attempts to use ``boost::optional`` instead of sol's own ``optional``
|
||||||
|
|
||||||
|
``SOL_ENABLE_INTEROP`` triggers the following change:
|
||||||
|
* Allows the use of ``extensible<T>`` to be used with ``userdata_checker`` and ``userdata_getter`` to retrieve non-sol usertypes
|
||||||
|
- Particularly enables non-sol usertypes to be used in overloads
|
||||||
|
- See the :ref:`stack dcoumentation` for details
|
||||||
|
* May come with a slight performance penalty: only recommended for those stuck with non-sol libraries that still need to leverage some of sol's power
|
||||||
|
* **Not** turned on by default under any settings: *this MUST be turned on manually*
|
||||||
|
|
||||||
``SOL_SAFE_USERTYPE`` triggers the following change:
|
``SOL_SAFE_USERTYPE`` triggers the following change:
|
||||||
* If the userdata to a usertype function is nil, will trigger an error instead of letting things go through and letting the system segfault/crash
|
* If the userdata to a usertype function is nil, will trigger an error instead of letting things go through and letting the system segfault/crash
|
||||||
* Turned on by default with clang++, g++ and VC++ if a basic check for building in debug mode is detected
|
* Turned on by default with clang++, g++ and VC++ if a basic check for building in debug mode is detected
|
||||||
|
@ -31,7 +38,7 @@ Note that you can obtain safety with regards to functions you bind by using the
|
||||||
|
|
||||||
``SOL_NO_CHECK_NUMBER_PRECISION`` triggers the following changes:
|
``SOL_NO_CHECK_NUMBER_PRECISION`` triggers the following changes:
|
||||||
* If ``SOL_CHECK_ARGUMENTS`` is defined, turns off number precision and integer precision fitting when pushing numbers into sol2
|
* If ``SOL_CHECK_ARGUMENTS`` is defined, turns off number precision and integer precision fitting when pushing numbers into sol2
|
||||||
* **Not** turned on by default under any settings: *thus MUSt be turned on manually*
|
* **Not** turned on by default under any settings: *this MUST be turned on manually*
|
||||||
|
|
||||||
``SOL_CHECK_ARGUMENTS`` triggers the following changes:
|
``SOL_CHECK_ARGUMENTS`` triggers the following changes:
|
||||||
* ``sol::stack::get`` (used everywhere) defaults to using ``sol::stack::check_get`` and dereferencing the argument. It uses ``sol::type_panic`` as the handler if something goes wrong
|
* ``sol::stack::get`` (used everywhere) defaults to using ``sol::stack::check_get`` and dereferencing the argument. It uses ``sol::type_panic`` as the handler if something goes wrong
|
||||||
|
|
|
@ -8,14 +8,17 @@ If you're already using lua and you just want to use ``sol`` in some places, you
|
||||||
:caption: using state_view
|
:caption: using state_view
|
||||||
:name: state-view-snippet
|
:name: state-view-snippet
|
||||||
|
|
||||||
void something_in_my_system (lua_State* L) {
|
int something_in_my_system (lua_State* L) {
|
||||||
// start using Sol with a pre-existing system
|
// start using Sol with a pre-existing system
|
||||||
sol::state_view lua(L); // non-owning
|
sol::state_view lua(L); // non-owning
|
||||||
|
|
||||||
lua.script("print('bark bark bark!')");
|
lua.script("print('bark bark bark!')");
|
||||||
|
|
||||||
sol::table expected_table(L); // get the table off the top of the stack
|
// get the table off the top of the stack
|
||||||
|
sol::table expected_table(L, -1);
|
||||||
// start using it...
|
// start using it...
|
||||||
|
|
||||||
|
return 0; // or whatever you require of working with a raw function
|
||||||
}
|
}
|
||||||
|
|
||||||
:doc:`sol::state_view<../api/state>` is exactly like ``sol::state``, but it doesn't manage the lifetime of a ``lua_State*``. Therefore, you get all the goodies that come with a ``sol::state`` without any of the ownership implications. Sol has no initialization components that need to deliberately remain alive for the duration of the program. It's entirely self-containing and uses lua's garbage collectors and various implementation techniques to require no state C++-side. After you do that, all of the power of `Sol` is available to you, and then some!
|
:doc:`sol::state_view<../api/state>` is exactly like ``sol::state``, but it doesn't manage the lifetime of a ``lua_State*``. Therefore, you get all the goodies that come with a ``sol::state`` without any of the ownership implications. Sol has no initialization components that need to deliberately remain alive for the duration of the program. It's entirely self-containing and uses lua's garbage collectors and various implementation techniques to require no state C++-side. After you do that, all of the power of `Sol` is available to you, and then some!
|
||||||
|
@ -26,8 +29,11 @@ You may also want to call ``require`` and supply a string of a script file or so
|
||||||
|
|
||||||
Remember that Sol can be as lightweight as you want it: almost all of Sol's Lua types take the ``lua_State*`` argument and then a second ``int index`` stack index argument, meaning you can use :doc:`tables<../api/table>`, :doc:`lua functions<../api/function>`, :doc:`coroutines<../api/coroutine>`, and other reference-derived objects that expose the proper constructor for your use. You can also set :doc:`usertypes<../api/usertype>` and other things you need without changing your entire architecture in one go.
|
Remember that Sol can be as lightweight as you want it: almost all of Sol's Lua types take the ``lua_State*`` argument and then a second ``int index`` stack index argument, meaning you can use :doc:`tables<../api/table>`, :doc:`lua functions<../api/function>`, :doc:`coroutines<../api/coroutine>`, and other reference-derived objects that expose the proper constructor for your use. You can also set :doc:`usertypes<../api/usertype>` and other things you need without changing your entire architecture in one go.
|
||||||
|
|
||||||
|
You can even customize it to `work with an external Lua wrapper/framework/library`_.
|
||||||
|
|
||||||
Note that you can also make non-standard pointer and reference types with custom reference counting and such also play nice with the system. See :doc:`unique_usertype_traits\<T><../api/unique_usertype_traits>` to see how! Custom types is also mentioned in the :doc:`customization tutorial<customization>`.
|
Note that you can also make non-standard pointer and reference types with custom reference counting and such also play nice with the system. See :doc:`unique_usertype_traits\<T><../api/unique_usertype_traits>` to see how! Custom types is also mentioned in the :doc:`customization tutorial<customization>`.
|
||||||
|
|
||||||
There are a few things that creating a ``sol::state`` does for you. You can read about it :ref:`in the sol::state docs<state-automatic-handlers>` and call those functions directly if you need them.
|
There are a few things that creating a ``sol::state`` does for you. You can read about it :ref:`in the sol::state docs<state-automatic-handlers>` and call those functions directly if you need them.
|
||||||
|
|
||||||
.. _create a DLL that loads some Lua module: https://github.com/ThePhD/sol2/tree/develop/examples/require_dll_example
|
.. _create a DLL that loads some Lua module: https://github.com/ThePhD/sol2/tree/develop/examples/require_dll_example
|
||||||
|
.. _work with an external Lua library: https://github.com/ThePhD/sol2/tree/develop/examples/interop
|
||||||
|
|
|
@ -24,6 +24,8 @@ The examples folder also has a number of really great examples for you to see. T
|
||||||
- Extend them using the :doc:`sol::unique_usertype\<T\> traits<api/unique_usertype_traits>`
|
- Extend them using the :doc:`sol::unique_usertype\<T\> traits<api/unique_usertype_traits>`
|
||||||
- This allows for custom smart pointers, special pointers, custom handles and others to be given certain handling semantics to ensure proper RAII with Lua's garbage collection
|
- This allows for custom smart pointers, special pointers, custom handles and others to be given certain handling semantics to ensure proper RAII with Lua's garbage collection
|
||||||
* (Advanced) You can override the iteration function for Lua 5.2 and above (LuaJIT does not have the capability) `as shown in the pairs example`_
|
* (Advanced) You can override the iteration function for Lua 5.2 and above (LuaJIT does not have the capability) `as shown in the pairs example`_
|
||||||
|
* (Advanced) Interop with ``toLua``, ``kaguya``, ``OOLua``, ``LuaBind``, ``luwra``, and all other existing libraries by using the stack API's ``sol::stack::userdata_checker`` and ``sol::stack::userdata_getter`` :ref:`extension points<extension_points>`
|
||||||
|
- Must turn on ``SOL_ENABLE_INTEROP``, as defined in the :ref:`configuration and safety documentation<config>`, to use
|
||||||
* Please note that the colon is necessary to "automatically" pass the ``this``/``self`` argument to Lua methods
|
* Please note that the colon is necessary to "automatically" pass the ``this``/``self`` argument to Lua methods
|
||||||
- ``obj:method_name()`` is how you call "member" methods in Lua
|
- ``obj:method_name()`` is how you call "member" methods in Lua
|
||||||
- It is purely syntactic sugar that passes the object name as the first argument to the ``method_name`` function
|
- It is purely syntactic sugar that passes the object name as the first argument to the ``method_name`` function
|
||||||
|
|
128
examples/interop/kaguya.cpp
Normal file
128
examples/interop/kaguya.cpp
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
#define SOL_CHECK_ARGUMENTS 1
|
||||||
|
#define SOL_ENABLE_INTEROP 1 // MUST be defined to use interop features
|
||||||
|
#include <sol.hpp>
|
||||||
|
|
||||||
|
#include "kaguya.hpp"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
// kaguya code lifted from README.md,
|
||||||
|
// written by satoren:
|
||||||
|
// https://github.com/satoren/kaguya
|
||||||
|
// Copyright satoren
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See
|
||||||
|
// accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
// http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
|
||||||
|
struct ABC {
|
||||||
|
ABC()
|
||||||
|
: v_(0) {
|
||||||
|
}
|
||||||
|
ABC(int value)
|
||||||
|
: v_(value) {
|
||||||
|
}
|
||||||
|
int value() const {
|
||||||
|
return v_;
|
||||||
|
}
|
||||||
|
void setValue(int v) {
|
||||||
|
v_ = v;
|
||||||
|
}
|
||||||
|
void overload1() {
|
||||||
|
std::cout << "call overload1" << std::endl;
|
||||||
|
}
|
||||||
|
void overload2(int) {
|
||||||
|
std::cout << "call overload2" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int v_;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace sol {
|
||||||
|
namespace stack {
|
||||||
|
template <typename T>
|
||||||
|
struct userdata_checker<extensible<T>> {
|
||||||
|
template <typename Handler>
|
||||||
|
static bool check(lua_State* L, int index, type index_type, Handler&& handler, record& tracking) {
|
||||||
|
// just marking unused parameters for no compiler warnings
|
||||||
|
(void)index_type;
|
||||||
|
(void)handler;
|
||||||
|
// using 1 element
|
||||||
|
tracking.use(1);
|
||||||
|
// use kaguya's own detail wrapper check to see if it's correct
|
||||||
|
bool is_correct_type = kaguya::detail::object_wrapper_type_check(L, index);
|
||||||
|
return is_correct_type;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct userdata_getter<extensible<T>> {
|
||||||
|
static std::pair<bool, T*> get(lua_State* L, int index, void* unadjusted_pointer, record& tracking) {
|
||||||
|
// you may not need to specialize this method every time:
|
||||||
|
// some libraries are compatible with sol2's layout
|
||||||
|
|
||||||
|
// kaguya's storage of data is incompatible with sol's
|
||||||
|
// it stores the data directly in the pointer, not a pointer inside of the `void*`
|
||||||
|
// therefore, leave the raw userdata pointer as-is,
|
||||||
|
// if it's of the right type
|
||||||
|
if (!kaguya::detail::object_wrapper_type_check(L, index)) {
|
||||||
|
return { false, nullptr };
|
||||||
|
}
|
||||||
|
// using 1 element
|
||||||
|
tracking.use(1);
|
||||||
|
kaguya::ObjectWrapperBase* base = kaguya::object_wrapper(L, index);
|
||||||
|
return { true, static_cast<T*>(base->get()) };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} // namespace sol::stack
|
||||||
|
|
||||||
|
void register_sol_stuff(lua_State* L) {
|
||||||
|
// grab raw state and put into state_view
|
||||||
|
// state_view is cheap to construct
|
||||||
|
sol::state_view lua(L);
|
||||||
|
// bind and set up your things: everything is entirely self-contained
|
||||||
|
lua["f"] = sol::overload(
|
||||||
|
[](ABC& from_kaguya) {
|
||||||
|
std::cout << "calling 1-argument version with kaguya-created ABC {" << from_kaguya.value() << "}" << std::endl;
|
||||||
|
},
|
||||||
|
[](ABC& from_kaguya, int second_arg) {
|
||||||
|
std::cout << "calling 2-argument version with kaguya-created ABC {" << from_kaguya.value() << "} and integer argument of " << second_arg << std::endl;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void check_with_sol(lua_State* L) {
|
||||||
|
sol::state_view lua(L);
|
||||||
|
ABC& obj = lua["obj"];
|
||||||
|
(void)obj;
|
||||||
|
assert(obj.value() == 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int, char* []) {
|
||||||
|
|
||||||
|
std::cout << "=== interop example (kaguya) ===" << std::endl;
|
||||||
|
std::cout << "(code lifted from kaguya's README examples: https://github.com/satoren/kaguya)" << std::endl;
|
||||||
|
|
||||||
|
kaguya::State state;
|
||||||
|
|
||||||
|
state["ABC"].setClass(kaguya::UserdataMetatable<ABC>()
|
||||||
|
.setConstructors<ABC(), ABC(int)>()
|
||||||
|
.addFunction("get_value", &ABC::value)
|
||||||
|
.addFunction("set_value", &ABC::setValue)
|
||||||
|
.addOverloadedFunctions("overload", &ABC::overload1, &ABC::overload2)
|
||||||
|
.addStaticFunction("nonmemberfun", [](ABC* self, int) { return 1; }));
|
||||||
|
|
||||||
|
|
||||||
|
register_sol_stuff(state.state());
|
||||||
|
|
||||||
|
state.dostring(R"(
|
||||||
|
obj = ABC.new(24)
|
||||||
|
f(obj) -- call 1 argument version
|
||||||
|
f(obj, 5) -- call 2 argument version
|
||||||
|
)");
|
||||||
|
|
||||||
|
check_with_sol(state.state());
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
11907
examples/interop/kaguya.hpp
Normal file
11907
examples/interop/kaguya.hpp
Normal file
File diff suppressed because it is too large
Load Diff
|
@ -66,6 +66,14 @@ namespace stack {
|
||||||
};
|
};
|
||||||
} // namespace stack_detail
|
} // namespace stack_detail
|
||||||
|
|
||||||
|
template <typename T, typename>
|
||||||
|
struct userdata_checker {
|
||||||
|
template <typename Handler>
|
||||||
|
static bool check(lua_State*, int, type, Handler&&, record&) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template <typename T, type expected, typename>
|
template <typename T, type expected, typename>
|
||||||
struct checker {
|
struct checker {
|
||||||
template <typename Handler>
|
template <typename Handler>
|
||||||
|
@ -401,7 +409,14 @@ namespace stack {
|
||||||
template <typename T, typename C>
|
template <typename T, typename C>
|
||||||
struct checker<detail::as_value_tag<T>, type::userdata, C> {
|
struct checker<detail::as_value_tag<T>, type::userdata, C> {
|
||||||
template <typename U, typename Handler>
|
template <typename U, typename Handler>
|
||||||
static bool check(types<U>, lua_State* L, type indextype, int index, Handler&& handler, record& tracking) {
|
static bool check(types<U>, lua_State* L, int index, type indextype, Handler&& handler, record& tracking) {
|
||||||
|
#ifdef SOL_ENABLE_INTEROP
|
||||||
|
userdata_checker<extensible<T>> uc;
|
||||||
|
(void)uc;
|
||||||
|
if (uc.check(L, index, indextype, handler, tracking)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif // interop extensibility
|
||||||
tracking.use(1);
|
tracking.use(1);
|
||||||
if (indextype != type::userdata) {
|
if (indextype != type::userdata) {
|
||||||
handler(L, index, type::userdata, indextype, "value is not a valid userdata");
|
handler(L, index, type::userdata, indextype, "value is not a valid userdata");
|
||||||
|
@ -447,7 +462,7 @@ namespace stack {
|
||||||
template <typename Handler>
|
template <typename Handler>
|
||||||
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
||||||
const type indextype = type_of(L, index);
|
const type indextype = type_of(L, index);
|
||||||
return checker<detail::as_value_tag<T>, type::userdata, C>{}.check(types<T>(), L, indextype, index, std::forward<Handler>(handler), tracking);
|
return checker<detail::as_value_tag<T>, type::userdata, C>{}.check(types<T>(), L, index, indextype, std::forward<Handler>(handler), tracking);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -109,6 +109,9 @@ namespace sol {
|
||||||
|
|
||||||
namespace stack {
|
namespace stack {
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct extensible {};
|
||||||
|
|
||||||
template <typename T, bool global = false, bool raw = false, typename = void>
|
template <typename T, bool global = false, bool raw = false, typename = void>
|
||||||
struct field_getter;
|
struct field_getter;
|
||||||
template <typename T, bool global = false, bool raw = false, typename = void>
|
template <typename T, bool global = false, bool raw = false, typename = void>
|
||||||
|
@ -118,12 +121,16 @@ namespace sol {
|
||||||
template <typename T, typename = void>
|
template <typename T, typename = void>
|
||||||
struct getter;
|
struct getter;
|
||||||
template <typename T, typename = void>
|
template <typename T, typename = void>
|
||||||
|
struct userdata_getter;
|
||||||
|
template <typename T, typename = void>
|
||||||
struct popper;
|
struct popper;
|
||||||
template <typename T, typename = void>
|
template <typename T, typename = void>
|
||||||
struct pusher;
|
struct pusher;
|
||||||
template <typename T, type = lua_type_of<T>::value, typename = void>
|
template <typename T, type = lua_type_of<T>::value, typename = void>
|
||||||
struct checker;
|
struct checker;
|
||||||
template <typename T, typename = void>
|
template <typename T, typename = void>
|
||||||
|
struct userdata_checker;
|
||||||
|
template <typename T, typename = void>
|
||||||
struct check_getter;
|
struct check_getter;
|
||||||
|
|
||||||
struct probe {
|
struct probe {
|
||||||
|
|
|
@ -44,6 +44,13 @@
|
||||||
namespace sol {
|
namespace sol {
|
||||||
namespace stack {
|
namespace stack {
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct userdata_getter<T> {
|
||||||
|
static std::pair<bool, T*> get(lua_State*, int, void*, record&) {
|
||||||
|
return { false, nullptr };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template <typename T, typename>
|
template <typename T, typename>
|
||||||
struct getter {
|
struct getter {
|
||||||
static T& get(lua_State* L, int index, record& tracking) {
|
static T& get(lua_State* L, int index, record& tracking) {
|
||||||
|
@ -628,7 +635,16 @@ namespace stack {
|
||||||
struct getter<detail::as_value_tag<T>> {
|
struct getter<detail::as_value_tag<T>> {
|
||||||
static T* get_no_lua_nil(lua_State* L, int index, record& tracking) {
|
static T* get_no_lua_nil(lua_State* L, int index, record& tracking) {
|
||||||
tracking.use(1);
|
tracking.use(1);
|
||||||
void** pudata = static_cast<void**>(lua_touserdata(L, index));
|
void* rawdata = lua_touserdata(L, index);
|
||||||
|
#ifdef SOL_ENABLE_INTEROP
|
||||||
|
userdata_getter<extensible<T>> ug;
|
||||||
|
(void)ug;
|
||||||
|
auto ugr = ug.get(L, index, rawdata, tracking);
|
||||||
|
if (ugr.first) {
|
||||||
|
return ugr.second;
|
||||||
|
}
|
||||||
|
#endif // interop extensibility
|
||||||
|
void** pudata = static_cast<void**>(rawdata);
|
||||||
void* udata = *pudata;
|
void* udata = *pudata;
|
||||||
return get_no_lua_nil_from(L, udata, index, tracking);
|
return get_no_lua_nil_from(L, udata, index, tracking);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user