mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
initial __type implementation, need to bikeshed over what goes in it and how to query information (sol::lib::extensions
time?)
fixed `sol::string_view` not pushing a string based on return type
This commit is contained in:
parent
a11e127d4d
commit
761641202f
|
@ -19,8 +19,10 @@ The examples folder also has a number of really great examples for you to see. T
|
||||||
- If you need dynamic callbacks or runtime overridable functions, have a ``std::function`` member variable and get/set it on the usertype object
|
- If you need dynamic callbacks or runtime overridable functions, have a ``std::function`` member variable and get/set it on the usertype object
|
||||||
- ``std::function`` works as a member variable or in passing as an argument / returning as a value (you can even use it with ``sol::property``)
|
- ``std::function`` works as a member variable or in passing as an argument / returning as a value (you can even use it with ``sol::property``)
|
||||||
- You can also create an entirely dynamic object: see the `dynamic_object example`_ for more details
|
- You can also create an entirely dynamic object: see the `dynamic_object example`_ for more details
|
||||||
* (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`_
|
|
||||||
* You can use :doc:`filters<api/filters>` to control dependencies and streamline return values, as well as apply custom behavior to a functions return
|
* You can use :doc:`filters<api/filters>` to control dependencies and streamline return values, as well as apply custom behavior to a functions return
|
||||||
|
* You can work with special wrapper types such as ``std::unique_ptr<T>``, ``std::shared_ptr<T>``, and others by default
|
||||||
|
- Extend them using the :doc:`sol::unique_usertype\<T\> traits<api/unique_usertype_traits>`
|
||||||
|
* (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`_
|
||||||
* 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
|
||||||
|
@ -32,13 +34,13 @@ The examples folder also has a number of really great examples for you to see. T
|
||||||
- You can retrieve a usertype from the Lua runtime at any time
|
- You can retrieve a usertype from the Lua runtime at any time
|
||||||
- Methods and properties will be added to the type only after you register the usertype with the Lua runtime
|
- Methods and properties will be added to the type only after you register the usertype with the Lua runtime
|
||||||
- All methods and properties will appear on all userdata, even if that object was pushed before the usertype (all userdata will be updated)
|
- All methods and properties will appear on all userdata, even if that object was pushed before the usertype (all userdata will be updated)
|
||||||
* Types either copy once or move once into the memory location, if it is a value type. If it is a pointer, we store only the reference.
|
* Types either copy once or move once into the memory location, if it is a value type. If it is a pointer, we store only the reference
|
||||||
- This means retrieval of class types (not primitive types like strings or integers) by ``T&`` or ``T*`` allow you to modify the data in Lua directly.
|
- This means retrieval of class types (not primitive types like strings or integers) by ``T&`` or ``T*`` allow you to modify the data in Lua directly
|
||||||
- Retrieve a plain ``T`` to get a copy
|
- Retrieve a plain ``T`` to get a copy
|
||||||
- Return types and passing arguments to ``sol::function``-types use perfect forwarding and reference semantics, which means no copies happen unless you specify a value explicitly. See :ref:`this note for details<function-argument-handling>`.
|
- Return types and passing arguments to ``sol::function``-types use perfect forwarding and reference semantics, which means no copies happen unless you specify a value explicitly. See :ref:`this note for details<function-argument-handling>`
|
||||||
* You can set ``index`` and ``new_index`` freely on any usertype you like to override the default "if a key is missing, find it / set it here" functionality of a specific object of a usertype.
|
* You can set ``index`` and ``new_index`` freely on any usertype you like to override the default "if a key is missing, find it / set it here" functionality of a specific object of a usertype
|
||||||
- ``new_index`` and ``index`` will not be called if you try to manipulate the named usertype table directly. sol2's will be called to add that function to the usertype's function/variable lookup table.
|
- ``new_index`` and ``index`` will not be called if you try to manipulate the named usertype table directly. sol2's will be called to add that function to the usertype's function/variable lookup table
|
||||||
- ``new_index`` and ``index`` will be called if you attempt to call a key that does not exist on an actual userdata object (the C++ object) itself.
|
- ``new_index`` and ``index`` will be called if you attempt to call a key that does not exist on an actual userdata object (the C++ object) itself
|
||||||
- If you made a usertype named ``test``, this means ``t = test()``, with ``t.hi = 54`` will call your function, but ``test.hi = function () print ("hi"); end`` will instead set the key ``hi`` to to lookup that function for all ``test`` types
|
- If you made a usertype named ``test``, this means ``t = test()``, with ``t.hi = 54`` will call your function, but ``test.hi = function () print ("hi"); end`` will instead set the key ``hi`` to to lookup that function for all ``test`` types
|
||||||
* The first ``sizeof( void* )`` bytes is always a pointer to the typed C++ memory. What comes after is based on what you've pushed into the system according to :doc:`the memory specification for usertypes<api/usertype_memory>`. This is compatible with a number of systems other than just sol2, making it easy to interop with select other Lua systems.
|
* The first ``sizeof( void* )`` bytes is always a pointer to the typed C++ memory. What comes after is based on what you've pushed into the system according to :doc:`the memory specification for usertypes<api/usertype_memory>`. This is compatible with a number of systems other than just sol2, making it easy to interop with select other Lua systems.
|
||||||
* Member methods, properties, variables and functions taking ``self&`` arguments modify data directly
|
* Member methods, properties, variables and functions taking ``self&`` arguments modify data directly
|
||||||
|
|
|
@ -302,8 +302,8 @@ namespace sol {
|
||||||
};
|
};
|
||||||
|
|
||||||
template <bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
|
template <bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
|
||||||
struct agnostic_lua_call_wrapper<lua_r_CFunction, is_index, is_variable, checked, boost, clean_stack, C> {
|
struct agnostic_lua_call_wrapper<lua_CFunction_ref, is_index, is_variable, checked, boost, clean_stack, C> {
|
||||||
static int call(lua_State* L, lua_r_CFunction f) {
|
static int call(lua_State* L, lua_CFunction_ref f) {
|
||||||
return f(L);
|
return f(L);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -64,12 +64,33 @@ namespace sol {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename F = void>
|
||||||
struct argument_handler {
|
struct argument_handler {
|
||||||
int operator()(lua_State* L, int index, type expected, type actual, const std::string& message) const noexcept(false) {
|
int operator()(lua_State* L, int index, type expected, type actual, const std::string& message) const noexcept(false) {
|
||||||
return type_panic_string(L, index, expected, actual, message + " (bad argument to variable or function call)");
|
return type_panic_string(L, index, expected, actual, message + " (bad argument to variable or function call)");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename R, typename... Args>
|
||||||
|
struct argument_handler<types<R, Args...>> {
|
||||||
|
int operator()(lua_State* L, int index, type expected, type actual, const std::string& message) const noexcept(false) {
|
||||||
|
std::string addendum = " (bad argument to type expecting '";
|
||||||
|
addendum += detail::demangle<R>();
|
||||||
|
addendum += "(";
|
||||||
|
int marker = 0;
|
||||||
|
auto action = [&addendum, &marker](const std::string& n) {
|
||||||
|
if (marker > 0) {
|
||||||
|
addendum += ", ";
|
||||||
|
}
|
||||||
|
addendum += n;
|
||||||
|
++marker;
|
||||||
|
}
|
||||||
|
(void)detail::swallow{ int(), (action(detail::demangle<Args>()), int())... };
|
||||||
|
addendum += ")')";
|
||||||
|
return type_panic_string(L, index, expected, actual, message + addendum);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Specify this function as the handler for lua::check if you know there's nothing wrong
|
// Specify this function as the handler for lua::check if you know there's nothing wrong
|
||||||
inline int no_panic(lua_State*, int, type, type, const char* = nullptr) noexcept {
|
inline int no_panic(lua_State*, int, type, type, const char* = nullptr) noexcept {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -184,7 +184,7 @@ namespace sol {
|
||||||
void* baseclasscast;
|
void* baseclasscast;
|
||||||
bool mustindex;
|
bool mustindex;
|
||||||
bool secondarymeta;
|
bool secondarymeta;
|
||||||
std::array<bool, 29> properties;
|
std::array<bool, 30> properties;
|
||||||
|
|
||||||
template <typename N>
|
template <typename N>
|
||||||
void insert(N&& n, object&& o) {
|
void insert(N&& n, object&& o) {
|
||||||
|
@ -415,6 +415,13 @@ namespace sol {
|
||||||
auto& properties = umx.properties;
|
auto& properties = umx.properties;
|
||||||
auto sic = hasindex ? &usertype_detail::simple_index_call<T, true> : &usertype_detail::simple_index_call<T, false>;
|
auto sic = hasindex ? &usertype_detail::simple_index_call<T, true> : &usertype_detail::simple_index_call<T, false>;
|
||||||
auto snic = hasnewindex ? &usertype_detail::simple_new_index_call<T, true> : &usertype_detail::simple_new_index_call<T, false>;
|
auto snic = hasnewindex ? &usertype_detail::simple_new_index_call<T, true> : &usertype_detail::simple_new_index_call<T, false>;
|
||||||
|
|
||||||
|
lua_createtable(L, 0, 2);
|
||||||
|
stack_reference type_table(L, -1);
|
||||||
|
|
||||||
|
stack::set_field(L, "name", detail::demangle<T>(), type_table.stack_index());
|
||||||
|
stack::set_field(L, "is", &usertype_detail::is_check<T>, type_table.stack_index());
|
||||||
|
|
||||||
auto register_kvp = [&](std::size_t meta_index, stack_reference& t, const std::string& first, object& second) {
|
auto register_kvp = [&](std::size_t meta_index, stack_reference& t, const std::string& first, object& second) {
|
||||||
meta_function mf = meta_function::construct;
|
meta_function mf = meta_function::construct;
|
||||||
for (std::size_t j = 1; j < properties.size(); ++j) {
|
for (std::size_t j = 1; j < properties.size(); ++j) {
|
||||||
|
@ -469,6 +476,8 @@ namespace sol {
|
||||||
}
|
}
|
||||||
luaL_newmetatable(L, metakey);
|
luaL_newmetatable(L, metakey);
|
||||||
stack_reference t(L, -1);
|
stack_reference t(L, -1);
|
||||||
|
stack::set_field(L, meta_function::type, type_table, t.stack_index());
|
||||||
|
|
||||||
for (auto& kvp : varmap.functions) {
|
for (auto& kvp : varmap.functions) {
|
||||||
auto& first = std::get<0>(kvp);
|
auto& first = std::get<0>(kvp);
|
||||||
auto& second = std::get<1>(kvp);
|
auto& second = std::get<1>(kvp);
|
||||||
|
@ -514,6 +523,7 @@ namespace sol {
|
||||||
// for call constructor purposes and such
|
// for call constructor purposes and such
|
||||||
lua_createtable(L, 0, 2 * static_cast<int>(umx.secondarymeta) + static_cast<int>(umx.callconstructfunc.valid()));
|
lua_createtable(L, 0, 2 * static_cast<int>(umx.secondarymeta) + static_cast<int>(umx.callconstructfunc.valid()));
|
||||||
stack_reference metabehind(L, -1);
|
stack_reference metabehind(L, -1);
|
||||||
|
stack::set_field(L, meta_function::type, type_table, metabehind.stack_index());
|
||||||
if (umx.callconstructfunc.valid()) {
|
if (umx.callconstructfunc.valid()) {
|
||||||
stack::set_field(L, sol::meta_function::call_function, umx.callconstructfunc, metabehind.stack_index());
|
stack::set_field(L, sol::meta_function::call_function, umx.callconstructfunc, metabehind.stack_index());
|
||||||
}
|
}
|
||||||
|
@ -538,6 +548,7 @@ namespace sol {
|
||||||
// Now for the shim-table that actually gets pushed
|
// Now for the shim-table that actually gets pushed
|
||||||
luaL_newmetatable(L, &usertype_traits<T>::user_metatable()[0]);
|
luaL_newmetatable(L, &usertype_traits<T>::user_metatable()[0]);
|
||||||
stack_reference t(L, -1);
|
stack_reference t(L, -1);
|
||||||
|
stack::set_field(L, meta_function::type, type_table, t.stack_index());
|
||||||
for (auto& kvp : varmap.functions) {
|
for (auto& kvp : varmap.functions) {
|
||||||
auto& first = std::get<0>(kvp);
|
auto& first = std::get<0>(kvp);
|
||||||
auto& second = std::get<1>(kvp);
|
auto& second = std::get<1>(kvp);
|
||||||
|
@ -546,6 +557,7 @@ namespace sol {
|
||||||
{
|
{
|
||||||
lua_createtable(L, 0, 2 + static_cast<int>(umx.callconstructfunc.valid()));
|
lua_createtable(L, 0, 2 + static_cast<int>(umx.callconstructfunc.valid()));
|
||||||
stack_reference metabehind(L, -1);
|
stack_reference metabehind(L, -1);
|
||||||
|
stack::set_field(L, meta_function::type, type_table, metabehind.stack_index());
|
||||||
if (umx.callconstructfunc.valid()) {
|
if (umx.callconstructfunc.valid()) {
|
||||||
stack::set_field(L, sol::meta_function::call_function, umx.callconstructfunc, metabehind.stack_index());
|
stack::set_field(L, sol::meta_function::call_function, umx.callconstructfunc, metabehind.stack_index());
|
||||||
}
|
}
|
||||||
|
@ -570,6 +582,8 @@ namespace sol {
|
||||||
metabehind.pop();
|
metabehind.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lua_remove(L, type_table.stack_index());
|
||||||
|
|
||||||
// Don't pop the table when we're done;
|
// Don't pop the table when we're done;
|
||||||
// return it
|
// return it
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -112,8 +112,8 @@ namespace sol {
|
||||||
inline decltype(auto) call(types<R>, types<Args...> ta, std::index_sequence<I...> tai, lua_State* L, int start, Fx&& fx, FxArgs&&... args) {
|
inline decltype(auto) call(types<R>, types<Args...> ta, std::index_sequence<I...> tai, lua_State* L, int start, Fx&& fx, FxArgs&&... args) {
|
||||||
#ifndef _MSC_VER
|
#ifndef _MSC_VER
|
||||||
static_assert(meta::all<meta::is_not_move_only<Args>...>::value, "One of the arguments being bound is a move-only type, and it is not being taken by reference: this will break your code. Please take a reference and std::move it manually if this was your intention.");
|
static_assert(meta::all<meta::is_not_move_only<Args>...>::value, "One of the arguments being bound is a move-only type, and it is not being taken by reference: this will break your code. Please take a reference and std::move it manually if this was your intention.");
|
||||||
#endif // This compiler make me so fucking sad
|
#endif // This compiler make me so sad
|
||||||
argument_handler handler{};
|
argument_handler<types<R, Args...>> handler{};
|
||||||
multi_check<checkargs, Args...>(L, start, handler);
|
multi_check<checkargs, Args...>(L, start, handler);
|
||||||
record tracking{};
|
record tracking{};
|
||||||
return evaluator{}.eval(ta, tai, L, start, tracking, std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
|
return evaluator{}.eval(ta, tai, L, start, tracking, std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
|
||||||
|
@ -124,7 +124,7 @@ namespace sol {
|
||||||
#ifndef _MSC_VER
|
#ifndef _MSC_VER
|
||||||
static_assert(meta::all<meta::is_not_move_only<Args>...>::value, "One of the arguments being bound is a move-only type, and it is not being taken by reference: this will break your code. Please take a reference and std::move it manually if this was your intention.");
|
static_assert(meta::all<meta::is_not_move_only<Args>...>::value, "One of the arguments being bound is a move-only type, and it is not being taken by reference: this will break your code. Please take a reference and std::move it manually if this was your intention.");
|
||||||
#endif // This compiler make me so fucking sad
|
#endif // This compiler make me so fucking sad
|
||||||
argument_handler handler{};
|
argument_handler<types<void, Args...>> handler{};
|
||||||
multi_check<checkargs, Args...>(L, start, handler);
|
multi_check<checkargs, Args...>(L, start, handler);
|
||||||
record tracking{};
|
record tracking{};
|
||||||
evaluator{}.eval(ta, tai, L, start, tracking, std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
|
evaluator{}.eval(ta, tai, L, start, tracking, std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
|
||||||
|
|
|
@ -880,7 +880,18 @@ namespace sol {
|
||||||
return std::visit(stack_detail::push_function(L), std::move(v));
|
return std::visit(stack_detail::push_function(L), std::move(v));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#endif
|
#else
|
||||||
|
template <>
|
||||||
|
struct pusher<string_view> {
|
||||||
|
static int push(lua_State* L, const std::string_view& sv) {
|
||||||
|
return stack::push(L, sv.data(), sv.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
static int push(lua_State* L, const std::string_view& sv, std::size_t len) {
|
||||||
|
return stack::push(L, sv.data(), len);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif // C++17 Support
|
||||||
} // stack
|
} // stack
|
||||||
} // sol
|
} // sol
|
||||||
|
|
||||||
|
|
|
@ -30,19 +30,33 @@
|
||||||
|
|
||||||
namespace sol {
|
namespace sol {
|
||||||
enum class lib : char {
|
enum class lib : char {
|
||||||
|
// print, assert, and other base functions
|
||||||
base,
|
base,
|
||||||
|
// require and other package functions
|
||||||
package,
|
package,
|
||||||
|
// coroutine functions and utilities
|
||||||
coroutine,
|
coroutine,
|
||||||
|
// string library
|
||||||
string,
|
string,
|
||||||
|
// functionality from the OS
|
||||||
os,
|
os,
|
||||||
|
// all things math
|
||||||
math,
|
math,
|
||||||
|
// the table manipulator and observer functions
|
||||||
table,
|
table,
|
||||||
|
// the debug library
|
||||||
debug,
|
debug,
|
||||||
|
// the bit library: different based on which you're using
|
||||||
bit32,
|
bit32,
|
||||||
|
// input/output library
|
||||||
io,
|
io,
|
||||||
|
// LuaJIT only
|
||||||
ffi,
|
ffi,
|
||||||
|
// LuaJIT only
|
||||||
jit,
|
jit,
|
||||||
|
// library for handling utf8: new to Lua
|
||||||
utf8,
|
utf8,
|
||||||
|
// do not use
|
||||||
count
|
count
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -186,7 +186,7 @@ namespace sol {
|
||||||
struct no_metatable_t {};
|
struct no_metatable_t {};
|
||||||
const no_metatable_t no_metatable = {};
|
const no_metatable_t no_metatable = {};
|
||||||
|
|
||||||
typedef std::remove_pointer_t<lua_CFunction> lua_r_CFunction;
|
typedef std::remove_pointer_t<lua_CFunction> lua_CFunction_ref;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct unique_usertype_traits {
|
struct unique_usertype_traits {
|
||||||
|
@ -617,13 +617,15 @@ namespace sol {
|
||||||
bitwise_or,
|
bitwise_or,
|
||||||
bitwise_xor,
|
bitwise_xor,
|
||||||
pairs,
|
pairs,
|
||||||
next
|
next,
|
||||||
|
type,
|
||||||
|
type_info,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef meta_function meta_method;
|
typedef meta_function meta_method;
|
||||||
|
|
||||||
inline const std::array<std::string, 29>& meta_function_names() {
|
inline const std::array<std::string, 31>& meta_function_names() {
|
||||||
static const std::array<std::string, 29> names = { {
|
static const std::array<std::string, 31> names = { {
|
||||||
"new",
|
"new",
|
||||||
"__index",
|
"__index",
|
||||||
"__newindex",
|
"__newindex",
|
||||||
|
@ -654,7 +656,9 @@ namespace sol {
|
||||||
"__bxor",
|
"__bxor",
|
||||||
|
|
||||||
"__pairs",
|
"__pairs",
|
||||||
"__next"
|
"__next",
|
||||||
|
"__type",
|
||||||
|
"__typeinfo"
|
||||||
} };
|
} };
|
||||||
return names;
|
return names;
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,11 @@ namespace sol {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
int is_check(lua_State* L) {
|
||||||
|
return stack::push(L, stack::check<T>(L, 1, &no_panic));
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline int member_default_to_string(std::true_type, lua_State* L) {
|
inline int member_default_to_string(std::true_type, lua_State* L) {
|
||||||
decltype(auto) ts = stack::get<T>(L, 1).to_string();
|
decltype(auto) ts = stack::get<T>(L, 1).to_string();
|
||||||
|
|
|
@ -379,7 +379,7 @@ namespace sol {
|
||||||
struct usertype_metatable<T, std::index_sequence<I...>, Tn...> : usertype_metatable_core, usertype_detail::registrar {
|
struct usertype_metatable<T, std::index_sequence<I...>, Tn...> : usertype_metatable_core, usertype_detail::registrar {
|
||||||
typedef std::make_index_sequence<sizeof...(I) * 2> indices;
|
typedef std::make_index_sequence<sizeof...(I) * 2> indices;
|
||||||
typedef std::index_sequence<I...> half_indices;
|
typedef std::index_sequence<I...> half_indices;
|
||||||
typedef std::array<luaL_Reg, sizeof...(Tn) / 2 + 1 + 29> regs_t;
|
typedef std::array<luaL_Reg, sizeof...(Tn) / 2 + 1 + 31> regs_t;
|
||||||
typedef std::tuple<Tn...> RawTuple;
|
typedef std::tuple<Tn...> RawTuple;
|
||||||
typedef std::tuple<clean_type_t<Tn> ...> Tuple;
|
typedef std::tuple<clean_type_t<Tn> ...> Tuple;
|
||||||
template <std::size_t Idx>
|
template <std::size_t Idx>
|
||||||
|
@ -394,7 +394,7 @@ namespace sol {
|
||||||
void* baseclasscheck;
|
void* baseclasscheck;
|
||||||
void* baseclasscast;
|
void* baseclasscast;
|
||||||
bool secondarymeta;
|
bool secondarymeta;
|
||||||
std::array<bool, 29> properties;
|
std::array<bool, 30> properties;
|
||||||
|
|
||||||
template <std::size_t Idx, meta::enable<std::is_same<lua_CFunction, meta::unqualified_tuple_element<Idx + 1, RawTuple>>> = meta::enabler>
|
template <std::size_t Idx, meta::enable<std::is_same<lua_CFunction, meta::unqualified_tuple_element<Idx + 1, RawTuple>>> = meta::enabler>
|
||||||
lua_CFunction make_func() const {
|
lua_CFunction make_func() const {
|
||||||
|
@ -676,6 +676,12 @@ namespace sol {
|
||||||
}
|
}
|
||||||
unique_table[lastreg - 1] = { value_table[lastreg - 1].name, detail::unique_destruct<T> };
|
unique_table[lastreg - 1] = { value_table[lastreg - 1].name, detail::unique_destruct<T> };
|
||||||
|
|
||||||
|
lua_createtable(L, 0, 2);
|
||||||
|
stack_reference type_table(L, -1);
|
||||||
|
|
||||||
|
stack::set_field(L, "name", detail::demangle<T>(), type_table.stack_index());
|
||||||
|
stack::set_field(L, "is", &usertype_detail::is_check<T>, type_table.stack_index());
|
||||||
|
|
||||||
// Now use um
|
// Now use um
|
||||||
const bool& mustindex = umc.mustindex;
|
const bool& mustindex = umc.mustindex;
|
||||||
for (std::size_t i = 0; i < 3; ++i) {
|
for (std::size_t i = 0; i < 3; ++i) {
|
||||||
|
@ -699,6 +705,7 @@ namespace sol {
|
||||||
}
|
}
|
||||||
luaL_newmetatable(L, metakey);
|
luaL_newmetatable(L, metakey);
|
||||||
stack_reference t(L, -1);
|
stack_reference t(L, -1);
|
||||||
|
stack::set_field(L, meta_function::type, type_table, t.stack_index());
|
||||||
int upvalues = 0;
|
int upvalues = 0;
|
||||||
upvalues += stack::push(L, nullptr);
|
upvalues += stack::push(L, nullptr);
|
||||||
upvalues += stack::push(L, make_light(um));
|
upvalues += stack::push(L, make_light(um));
|
||||||
|
@ -735,6 +742,9 @@ namespace sol {
|
||||||
stack::set_field(L, meta_function::index, make_closure(umt_t::index_call, nullptr, make_light(um), make_light(umc)), metabehind.stack_index());
|
stack::set_field(L, meta_function::index, make_closure(umt_t::index_call, nullptr, make_light(um), make_light(umc)), metabehind.stack_index());
|
||||||
stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, nullptr, make_light(um), make_light(umc)), metabehind.stack_index());
|
stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, nullptr, make_light(um), make_light(umc)), metabehind.stack_index());
|
||||||
}
|
}
|
||||||
|
// type information needs to be present on the behind-tables too
|
||||||
|
stack::set_field(L, meta_function::type, type_table, metabehind.stack_index());
|
||||||
|
|
||||||
stack::set_field(L, metatable_key, metabehind, t.stack_index());
|
stack::set_field(L, metatable_key, metabehind, t.stack_index());
|
||||||
metabehind.pop();
|
metabehind.pop();
|
||||||
// We want to just leave the table
|
// We want to just leave the table
|
||||||
|
@ -745,6 +755,7 @@ namespace sol {
|
||||||
// Now for the shim-table that actually gets assigned to the name
|
// Now for the shim-table that actually gets assigned to the name
|
||||||
luaL_newmetatable(L, &usertype_traits<T>::user_metatable()[0]);
|
luaL_newmetatable(L, &usertype_traits<T>::user_metatable()[0]);
|
||||||
stack_reference t(L, -1);
|
stack_reference t(L, -1);
|
||||||
|
stack::set_field(L, meta_function::type, type_table, t.stack_index());
|
||||||
int upvalues = 0;
|
int upvalues = 0;
|
||||||
upvalues += stack::push(L, nullptr);
|
upvalues += stack::push(L, nullptr);
|
||||||
upvalues += stack::push(L, make_light(um));
|
upvalues += stack::push(L, make_light(um));
|
||||||
|
@ -758,11 +769,14 @@ namespace sol {
|
||||||
|
|
||||||
stack::set_field(L, meta_function::index, make_closure(umt_t::index_call, nullptr, make_light(um), make_light(umc), nullptr, usertype_detail::toplevel_magic), metabehind.stack_index());
|
stack::set_field(L, meta_function::index, make_closure(umt_t::index_call, nullptr, make_light(um), make_light(umc), nullptr, usertype_detail::toplevel_magic), metabehind.stack_index());
|
||||||
stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, nullptr, make_light(um), make_light(umc), nullptr, usertype_detail::toplevel_magic), metabehind.stack_index());
|
stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, nullptr, make_light(um), make_light(umc), nullptr, usertype_detail::toplevel_magic), metabehind.stack_index());
|
||||||
|
|
||||||
stack::set_field(L, metatable_key, metabehind, t.stack_index());
|
stack::set_field(L, metatable_key, metabehind, t.stack_index());
|
||||||
|
// type information needs to be present on the behind-tables too
|
||||||
|
stack::set_field(L, meta_function::type, type_table, metabehind.stack_index());
|
||||||
metabehind.pop();
|
metabehind.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lua_remove(L, type_table.stack_index());
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -888,3 +888,35 @@ TEST_CASE("simple_usertype/indexing", "make sure simple usertypes can be indexed
|
||||||
REQUIRE(val == 50);
|
REQUIRE(val == 50);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("simple_usertype/basic type information", "check that we can query some basic type information") {
|
||||||
|
struct my_thing {};
|
||||||
|
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::base);
|
||||||
|
|
||||||
|
lua.new_usertype<my_thing>("my_thing");
|
||||||
|
|
||||||
|
lua.safe_script("obj = my_thing.new()");
|
||||||
|
|
||||||
|
lua.safe_script("assert(my_thing.__type.is(obj))");
|
||||||
|
lua.safe_script("assert(not my_thing.__type.is(1))");
|
||||||
|
lua.safe_script("assert(not my_thing.__type.is(\"not a thing\"))");
|
||||||
|
lua.safe_script("print(my_thing.__type.name)");
|
||||||
|
|
||||||
|
lua.safe_script("assert(obj.__type.is(obj))");
|
||||||
|
lua.safe_script("assert(not obj.__type.is(1))");
|
||||||
|
lua.safe_script("assert(not obj.__type.is(\"not a thing\"))");
|
||||||
|
lua.safe_script("print(obj.__type.name)");
|
||||||
|
|
||||||
|
lua.safe_script("assert(getmetatable(my_thing).__type.is(obj))");
|
||||||
|
lua.safe_script("assert(not getmetatable(my_thing).__type.is(1))");
|
||||||
|
lua.safe_script("assert(not getmetatable(my_thing).__type.is(\"not a thing\"))");
|
||||||
|
lua.safe_script("print(getmetatable(my_thing).__type.name)");
|
||||||
|
|
||||||
|
lua.safe_script("assert(getmetatable(obj).__type.is(obj))");
|
||||||
|
lua.safe_script("assert(not getmetatable(obj).__type.is(1))");
|
||||||
|
lua.safe_script("assert(not getmetatable(obj).__type.is(\"not a thing\"))");
|
||||||
|
lua.safe_script("print(getmetatable(obj).__type.name)");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -115,8 +115,23 @@ TEST_CASE("object/string-pushers", "test some basic string pushers with in_place
|
||||||
|
|
||||||
sol::object ocs(lua, sol::in_place, "bark\0bark", 9);
|
sol::object ocs(lua, sol::in_place, "bark\0bark", 9);
|
||||||
sol::object os(lua, sol::in_place_type<std::string>, std::string("bark\0bark", 9), 8);
|
sol::object os(lua, sol::in_place_type<std::string>, std::string("bark\0bark", 9), 8);
|
||||||
bool test1 = os.as<std::string>() == std::string("bark\0bar", 8);
|
sol::object osv(lua, sol::in_place_type<sol::string_view>, std::string_view("woofwoof", 8), 8);
|
||||||
bool test2 = ocs.as<std::string>() == std::string("bark\0bark", 9);
|
bool test1 = ocs.as<std::string>() == std::string("bark\0bark", 9);
|
||||||
|
bool test2 = os.as<std::string>() == std::string("bark\0bar", 8);
|
||||||
|
bool test3 = osv.as<std::string>() == std::string("woofwoof", 8);
|
||||||
|
REQUIRE(ocs.get_type() == sol::type::string);
|
||||||
|
REQUIRE(ocs.is<std::string>());
|
||||||
|
REQUIRE(ocs.is<sol::string_view>());
|
||||||
|
|
||||||
|
REQUIRE(os.get_type() == sol::type::string);
|
||||||
|
REQUIRE(os.is<std::string>());
|
||||||
|
REQUIRE(os.is<sol::string_view>());
|
||||||
|
|
||||||
|
REQUIRE(osv.get_type() == sol::type::string);
|
||||||
|
REQUIRE(osv.is<std::string>());
|
||||||
|
REQUIRE(osv.is<sol::string_view>());
|
||||||
|
|
||||||
REQUIRE(test1);
|
REQUIRE(test1);
|
||||||
REQUIRE(test2);
|
REQUIRE(test2);
|
||||||
|
REQUIRE(test3);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1764,3 +1764,34 @@ TEST_CASE("usertype/noexcept-methods", "make sure noexcept functinos and methods
|
||||||
REQUIRE(v1 == 0x61);
|
REQUIRE(v1 == 0x61);
|
||||||
REQUIRE(v2 == 0x62);
|
REQUIRE(v2 == 0x62);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("usertype/basic type information", "check that we can query some basic type information") {
|
||||||
|
struct my_thing {};
|
||||||
|
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::base);
|
||||||
|
|
||||||
|
lua.new_simple_usertype<my_thing>("my_thing");
|
||||||
|
|
||||||
|
lua.safe_script("obj = my_thing.new()");
|
||||||
|
|
||||||
|
lua.safe_script("assert(my_thing.__type.is(obj))");
|
||||||
|
lua.safe_script("assert(not my_thing.__type.is(1))");
|
||||||
|
lua.safe_script("assert(not my_thing.__type.is(\"not a thing\"))");
|
||||||
|
lua.safe_script("print(my_thing.__type.name)");
|
||||||
|
|
||||||
|
lua.safe_script("assert(obj.__type.is(obj))");
|
||||||
|
lua.safe_script("assert(not obj.__type.is(1))");
|
||||||
|
lua.safe_script("assert(not obj.__type.is(\"not a thing\"))");
|
||||||
|
lua.safe_script("print(obj.__type.name)");
|
||||||
|
|
||||||
|
lua.safe_script("assert(getmetatable(my_thing).__type.is(obj))");
|
||||||
|
lua.safe_script("assert(not getmetatable(my_thing).__type.is(1))");
|
||||||
|
lua.safe_script("assert(not getmetatable(my_thing).__type.is(\"not a thing\"))");
|
||||||
|
lua.safe_script("print(getmetatable(my_thing).__type.name)");
|
||||||
|
|
||||||
|
lua.safe_script("assert(getmetatable(obj).__type.is(obj))");
|
||||||
|
lua.safe_script("assert(not getmetatable(obj).__type.is(1))");
|
||||||
|
lua.safe_script("assert(not getmetatable(obj).__type.is(\"not a thing\"))");
|
||||||
|
lua.safe_script("print(getmetatable(obj).__type.name)");
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user