mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
This commit adds some QoI constructor keys / types, as well as implements make_object
. The documentation has been updated as well.
Closes #78 Closes #77 Closes #76 Closes #75
This commit is contained in:
parent
06fecfb4ca
commit
9e31119f16
|
@ -26,6 +26,7 @@ Browse the various function and classes :doc:`Sol<../index>` utilizes to make yo
|
|||
optional
|
||||
state
|
||||
table
|
||||
metatable_key
|
||||
this_state
|
||||
thread
|
||||
tie
|
||||
|
|
45
docs/source/api/metatable_key.rst
Normal file
45
docs/source/api/metatable_key.rst
Normal file
|
@ -0,0 +1,45 @@
|
|||
metatable_key
|
||||
=============
|
||||
A key for setting and getting an object's metatable
|
||||
---------------------------------------------------
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
struct metatable_key_t {};
|
||||
const metatable_key_t metatable_key;
|
||||
|
||||
You can use this in conjunction with :doc:`sol::table<table>` to set/get a metatable. Lua metatables are powerful ways to override default behavior of objects for various kinds of operators, among other things. Here is an entirely complete example, showing getting and working with a :doc:`usertype<usertype>`'s metatable defined by Sol:
|
||||
|
||||
.. code-block:: cpp
|
||||
:caption: messing with metatables
|
||||
:linenos:
|
||||
|
||||
#include <sol.hpp>
|
||||
|
||||
int main () {
|
||||
|
||||
struct bark {
|
||||
int operator()(int x) {
|
||||
return x;
|
||||
}
|
||||
};
|
||||
|
||||
sol::state lua;
|
||||
lua.open_libraries(sol::lib::base);
|
||||
|
||||
lua.new_usertype<bark>("bark",
|
||||
sol::meta_function::call_function, &bark::operator()
|
||||
);
|
||||
|
||||
bark b;
|
||||
lua.set("b", &b);
|
||||
|
||||
sol::table b_as_table = lua["b"];
|
||||
sol::table b_metatable = b_as_table[sol::metatable_key];
|
||||
sol::function b_call = b_metatable["__call"];
|
||||
sol::function b_as_function = lua["b"];
|
||||
|
||||
int result1 = b_as_function(1);
|
||||
int result2 = b_call(b, 1);
|
||||
// result1 == result2 == 1
|
||||
}
|
|
@ -49,4 +49,23 @@ non-members
|
|||
bool operator!=(const object& lhs, const nil_t&);
|
||||
bool operator!=(const nil_t&, const object& rhs);
|
||||
|
||||
These allow a person to compare an ``sol::object`` against :ref:`nil<nil>`, which essentially checks if an object references a non-nil value, like so:
|
||||
These allow a person to compare an ``sol::object`` against :ref:`nil<nil>`, which essentially checks if an object references a non-nil value, like so:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
if (myobj == sol::nil) {
|
||||
// doesn't have anything...
|
||||
}
|
||||
|
||||
Use this to check objects.
|
||||
|
||||
.. code-block:: cpp
|
||||
:caption: function: make object
|
||||
:name: make-object
|
||||
|
||||
template <typename T>
|
||||
object make_object(lua_State* L, T&& value);
|
||||
template <typename T, typename... Args>
|
||||
object make_object(lua_State* L, Args&&... args);
|
||||
|
||||
Makes an object out of the value. It pushes it onto the stack, then pops it into the returned ``sol::object``.
|
|
@ -43,7 +43,7 @@ The value of the reference in the registry.
|
|||
bool valid () const noexcept;
|
||||
explicit operator bool () const noexcept;
|
||||
|
||||
These functions check if the reference at ``T`` is valid: that is, if it is not :doc:`nil<types>` and if it is not non-existing (doesn't refer to anything, including nil) reference. The explicit operator bool allows you to use it in the context of an ``if ( my_obj )`` context.
|
||||
These functions check if the reference at ``T`` is valid: that is, if it is not :ref:`nil<nil>` and if it is not non-existing (doesn't refer to anything, including nil) reference. The explicit operator bool allows you to use it in the context of an ``if ( my_obj )`` context.
|
||||
|
||||
.. code-block:: cpp
|
||||
:caption: function: retrieves the type
|
||||
|
@ -57,4 +57,19 @@ Gets the :doc:`sol::type<types>` of the reference; that is, the Lua reference.
|
|||
|
||||
lua_State* lua_state() const noexcept;
|
||||
|
||||
Gets the ``lua_State*`` this reference exists in.
|
||||
Gets the ``lua_State*`` this reference exists in.
|
||||
|
||||
|
||||
non-members
|
||||
-----------
|
||||
|
||||
.. code-block:: cpp
|
||||
:caption: functions: reference comparators
|
||||
|
||||
bool operator==(const reference&, const reference&);
|
||||
bool operator!=(const reference&, const reference&);
|
||||
|
||||
Compares two references using the Lua API's `lua_compare`_ for equality.
|
||||
|
||||
|
||||
.. _lua_compare: https://www.lua.org/manual/5.3/manual.html#lua_compare
|
|
@ -1,5 +1,5 @@
|
|||
userdata
|
||||
===========
|
||||
========
|
||||
reference to a userdata
|
||||
-----------------------
|
||||
|
||||
|
|
|
@ -149,6 +149,10 @@ The constructor of usertype takes a variable number of arguments. It takes an ev
|
|||
* ``"{name}", sol::initializers( func1, func2, ... )``
|
||||
- Creates initializers that, given one or more functions, provides an overloaded lua function for creating a the specified type.
|
||||
+ The function must have the argument signature ``func( T*, Arguments... )`` or ``func( T&, Arguments... )``, where the pointer or reference will point to a place of allocated memory that has an uninitialized ``T``. Note that lua controls the memory.
|
||||
* ``"{name}", sol::no_constructor``
|
||||
- Specifically tells Sol not to create a `.new()` if one is not specified and the type is default-constructible.
|
||||
* ``sol::call_constructor, {any constructor type}``
|
||||
- Specifies a function that makes the call turn into ``{usertype-name}( ... constructor arguments ... )``. This is compatible with luabind syntax.
|
||||
|
||||
.. _destructor:
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ inline int construct(Match&& matchfx, lua_State* L, int fxarity, int start) {
|
|||
template <typename T, typename... TypeLists>
|
||||
inline int construct(lua_State* L) {
|
||||
static const auto& meta = usertype_traits<T>::metatable;
|
||||
call_syntax syntax = stack::get_call_syntax(L, meta);
|
||||
call_syntax syntax = stack::get_call_syntax(L, meta, 1);
|
||||
int argcount = lua_gettop(L) - static_cast<int>(syntax);
|
||||
|
||||
T** pointerpointer = reinterpret_cast<T**>(lua_newuserdata(L, sizeof(T*) + sizeof(T)));
|
||||
|
|
|
@ -70,6 +70,22 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
object make_object(lua_State* L, T&& value) {
|
||||
int backpedal = stack::push(L, std::forward<T>(value));
|
||||
object r = stack::get<object>(L, -backpedal);
|
||||
lua_pop(L, backpedal);
|
||||
return r;
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
object make_object(lua_State* L, Args&&... args) {
|
||||
int backpedal = stack::push<T>(L, std::forward<Args>(args)...);
|
||||
object r = stack::get<sol::object>(L, -backpedal);
|
||||
lua_pop(L, backpedal);
|
||||
return r;
|
||||
}
|
||||
|
||||
inline bool operator==(const object& lhs, const nil_t&) {
|
||||
return !lhs.valid();
|
||||
}
|
||||
|
|
|
@ -62,6 +62,12 @@ using constructors = constructor_list<Args...>;
|
|||
|
||||
const auto default_constructor = constructors<types<>>{};
|
||||
|
||||
struct no_construction {};
|
||||
const auto no_constructor = no_construction{};
|
||||
|
||||
struct call_construction {};
|
||||
const auto call_constructor = call_construction{};
|
||||
|
||||
template <typename... Functions>
|
||||
struct constructor_wrapper {
|
||||
std::tuple<Functions...> set;
|
||||
|
|
|
@ -144,6 +144,16 @@ public:
|
|||
return L;
|
||||
}
|
||||
};
|
||||
|
||||
inline bool operator== (const reference& l, const reference& r) {
|
||||
auto ppl = stack::push_pop(l);
|
||||
auto ppr = stack::push_pop(r);
|
||||
return lua_compare(l.lua_state(), -1, -2, LUA_OPEQ) == 0;
|
||||
}
|
||||
|
||||
inline bool operator!= (const reference& l, const reference& r) {
|
||||
return !operator==(l, r);
|
||||
}
|
||||
} // sol
|
||||
|
||||
#endif // SOL_REFERENCE_HPP
|
||||
|
|
|
@ -93,7 +93,7 @@ inline void call(types<void>, types<Args...> ta, std::index_sequence<I...> tai,
|
|||
inline void remove( lua_State* L, int index, int count ) {
|
||||
if ( count < 1 )
|
||||
return;
|
||||
int top = lua_gettop( L );
|
||||
int top = lua_gettop(L);
|
||||
if ( index == -1 || top == index ) {
|
||||
// Slice them right off the top
|
||||
lua_pop( L, static_cast<int>(count) );
|
||||
|
@ -104,11 +104,11 @@ inline void remove( lua_State* L, int index, int count ) {
|
|||
// Probably slower, maybe, haven't benchmarked,
|
||||
// but necessary
|
||||
if ( index < 0 ) {
|
||||
index = lua_gettop( L ) + (index + 1);
|
||||
index = lua_gettop(L) + (index + 1);
|
||||
}
|
||||
int last = index + count;
|
||||
for ( int i = index; i < last; ++i ) {
|
||||
lua_remove( L, i );
|
||||
lua_remove(L, i);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -160,9 +160,9 @@ inline int call_into_lua(types<Ret0, Ret...>, types<Args...> ta, lua_State* L, i
|
|||
return push_reference(L, std::forward<decltype(r)>(r));
|
||||
}
|
||||
|
||||
inline call_syntax get_call_syntax(lua_State* L, const std::string& key) {
|
||||
inline call_syntax get_call_syntax(lua_State* L, const std::string& key, int index = -2) {
|
||||
luaL_getmetatable(L, key.c_str());
|
||||
if (lua_compare(L, -1, -2, LUA_OPEQ) == 1) {
|
||||
if (lua_compare(L, -1, index, LUA_OPEQ) == 1) {
|
||||
lua_pop(L, 1);
|
||||
return call_syntax::colon;
|
||||
}
|
||||
|
|
|
@ -41,7 +41,8 @@ struct field_getter {
|
|||
template <bool b, typename C>
|
||||
struct field_getter<metatable_key_t, b, C> {
|
||||
void get(lua_State* L, metatable_key_t, int tableindex = -1) {
|
||||
lua_getmetatable( L, tableindex );
|
||||
if (lua_getmetatable(L, tableindex) == 0)
|
||||
push(L, nil);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -166,7 +167,7 @@ template <typename... Args, bool b, typename C>
|
|||
struct field_setter<std::tuple<Args...>, b, C> {
|
||||
template <bool g, std::size_t I, typename Key, typename Value>
|
||||
void apply(std::index_sequence<I>, lua_State* L, Key&& keys, Value&& value, int tableindex) {
|
||||
I > 0 ?
|
||||
I < 1 ?
|
||||
set_field<g>(L, detail::forward_get<I>(keys), std::forward<Value>(value)) :
|
||||
set_field<g>(L, detail::forward_get<I>(keys), std::forward<Value>(value), tableindex);
|
||||
}
|
||||
|
|
|
@ -1,73 +1,81 @@
|
|||
// The MIT License (MIT)
|
||||
|
||||
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#ifndef SOL_STACK_REFERENCE_HPP
|
||||
#define SOL_STACK_REFERENCE_HPP
|
||||
|
||||
namespace sol {
|
||||
class stack_reference {
|
||||
private:
|
||||
lua_State* L = nullptr;
|
||||
int index = 0;
|
||||
|
||||
protected:
|
||||
int registry_index () const noexcept {
|
||||
return LUA_NOREF;
|
||||
}
|
||||
|
||||
public:
|
||||
stack_reference() noexcept = default;
|
||||
stack_reference(lua_State* L, int i) noexcept : L(L), index(lua_absindex(L, i)) {}
|
||||
stack_reference(stack_reference&& o) noexcept = default;
|
||||
stack_reference& operator=(stack_reference&&) noexcept = default;
|
||||
stack_reference(const stack_reference&) noexcept = default;
|
||||
stack_reference& operator=(const stack_reference&) noexcept = default;
|
||||
|
||||
int push() const noexcept {
|
||||
lua_pushvalue(L, index);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void pop(int n = 1) const noexcept {
|
||||
lua_pop(lua_state( ), n);
|
||||
}
|
||||
|
||||
int stack_index () const noexcept {
|
||||
return index;
|
||||
}
|
||||
|
||||
type get_type() const noexcept {
|
||||
int result = lua_type(L, index);
|
||||
return static_cast<type>(result);
|
||||
}
|
||||
|
||||
lua_State* lua_state() const noexcept {
|
||||
return L;
|
||||
}
|
||||
|
||||
bool valid () const noexcept {
|
||||
type t = get_type();
|
||||
return t != type::nil && t != type::none;
|
||||
}
|
||||
};
|
||||
} // sol
|
||||
|
||||
#endif // SOL_STACK_REFERENCE_HPP
|
||||
// The MIT License (MIT)
|
||||
|
||||
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#ifndef SOL_STACK_REFERENCE_HPP
|
||||
#define SOL_STACK_REFERENCE_HPP
|
||||
|
||||
namespace sol {
|
||||
class stack_reference {
|
||||
private:
|
||||
lua_State* L = nullptr;
|
||||
int index = 0;
|
||||
|
||||
protected:
|
||||
int registry_index () const noexcept {
|
||||
return LUA_NOREF;
|
||||
}
|
||||
|
||||
public:
|
||||
stack_reference() noexcept = default;
|
||||
stack_reference(lua_State* L, int i) noexcept : L(L), index(lua_absindex(L, i)) {}
|
||||
stack_reference(stack_reference&& o) noexcept = default;
|
||||
stack_reference& operator=(stack_reference&&) noexcept = default;
|
||||
stack_reference(const stack_reference&) noexcept = default;
|
||||
stack_reference& operator=(const stack_reference&) noexcept = default;
|
||||
|
||||
int push() const noexcept {
|
||||
lua_pushvalue(L, index);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void pop(int n = 1) const noexcept {
|
||||
lua_pop(lua_state( ), n);
|
||||
}
|
||||
|
||||
int stack_index () const noexcept {
|
||||
return index;
|
||||
}
|
||||
|
||||
type get_type() const noexcept {
|
||||
int result = lua_type(L, index);
|
||||
return static_cast<type>(result);
|
||||
}
|
||||
|
||||
lua_State* lua_state() const noexcept {
|
||||
return L;
|
||||
}
|
||||
|
||||
bool valid () const noexcept {
|
||||
type t = get_type();
|
||||
return t != type::nil && t != type::none;
|
||||
}
|
||||
};
|
||||
|
||||
inline bool operator== (const stack_reference& l, const stack_reference& r) {
|
||||
return lua_compare(l.lua_state(), l.stack_index(), l.stack_index(), LUA_OPEQ) == 0;
|
||||
}
|
||||
|
||||
inline bool operator!= (const stack_reference& l, const stack_reference& r) {
|
||||
return !operator==(l, r);
|
||||
}
|
||||
} // sol
|
||||
|
||||
#endif // SOL_STACK_REFERENCE_HPP
|
||||
|
|
|
@ -48,6 +48,9 @@ struct is_constructor<constructors<Args...>> : std::true_type {};
|
|||
template <typename... Args>
|
||||
struct is_constructor<constructor_wrapper<Args...>> : std::true_type {};
|
||||
|
||||
template <>
|
||||
struct is_constructor<no_construction> : std::true_type {};
|
||||
|
||||
template <typename... Args>
|
||||
using has_constructor = meta::Or<is_constructor<meta::Unqualified<Args>>...>;
|
||||
|
||||
|
@ -179,6 +182,7 @@ private:
|
|||
function_detail::base_function* indexfunc;
|
||||
function_detail::base_function* newindexfunc;
|
||||
function_map_t indexwrapper, newindexwrapper;
|
||||
const char* constructfuncname;
|
||||
lua_CFunction constructfunc;
|
||||
const char* destructfuncname;
|
||||
lua_CFunction destructfunc;
|
||||
|
@ -263,12 +267,16 @@ private:
|
|||
return make_functor_function(std::is_base_of<Arg0, T>(), name, std::forward<Fx>(func));
|
||||
}
|
||||
|
||||
template<std::size_t N>
|
||||
void build_function(std::string funcname, no_construction) {}
|
||||
|
||||
template<std::size_t N, typename... Args>
|
||||
void build_function(std::string funcname, constructors<Args...>) {
|
||||
functionnames.push_back(std::move(funcname));
|
||||
std::string& name = functionnames.back();
|
||||
// Insert bubble to keep with compile-time argument count (simpler and cheaper to do)
|
||||
functions.push_back(nullptr);
|
||||
constructfuncname = name.c_str();
|
||||
constructfunc = function_detail::construct<T, Args...>;
|
||||
metafunctiontable.push_back({ name.c_str(), constructfunc });
|
||||
}
|
||||
|
@ -283,27 +291,28 @@ private:
|
|||
|
||||
auto metamethodfind = std::find(meta_function_names.begin(), meta_function_names.end(), name);
|
||||
if (metamethodfind != meta_function_names.end()) {
|
||||
metafunctiontable.push_back({ name.c_str(), function_detail::usertype_call<N> });
|
||||
meta_function metafunction = static_cast<meta_function>(metamethodfind - meta_function_names.begin());
|
||||
switch (metafunction) {
|
||||
case meta_function::garbage_collect:
|
||||
destructfuncname = name.c_str();
|
||||
destructfunc = function_detail::usertype_call<N>;
|
||||
return;
|
||||
case meta_function::index:
|
||||
indexfunc = functions.back().get();
|
||||
needsindexfunction = true;
|
||||
break;
|
||||
case meta_function::new_index:
|
||||
newindexfunc = functions.back().get();
|
||||
break;
|
||||
case meta_function::construct:
|
||||
constructfunc = function_detail::usertype_call<N>;
|
||||
break;
|
||||
metafunctiontable.push_back({ name.c_str(), function_detail::usertype_call<N> });
|
||||
meta_function metafunction = static_cast<meta_function>(metamethodfind - meta_function_names.begin());
|
||||
switch (metafunction) {
|
||||
case meta_function::garbage_collect:
|
||||
destructfuncname = name.c_str();
|
||||
destructfunc = function_detail::usertype_call<N>;
|
||||
return;
|
||||
case meta_function::index:
|
||||
indexfunc = functions.back().get();
|
||||
needsindexfunction = true;
|
||||
break;
|
||||
case meta_function::new_index:
|
||||
newindexfunc = functions.back().get();
|
||||
break;
|
||||
case meta_function::construct:
|
||||
constructfuncname = name.c_str();
|
||||
constructfunc = function_detail::usertype_call<N>;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
functiontable.push_back({ name.c_str(), direct });
|
||||
}
|
||||
|
@ -396,6 +405,11 @@ private:
|
|||
build_function_tables<N>(funcname, std::forward<Fx>(func), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<std::size_t N, typename Fx, typename... Args>
|
||||
void build_function_tables(call_construction, Fx&& func, Args&&... args) {
|
||||
build_function_tables<N>("__call", std::forward<Fx>(func), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<std::size_t N, typename... Bases, typename... Args>
|
||||
void build_function_tables(base_classes_tag, bases<Bases...>, Args&&... args) {
|
||||
build_function_tables<N>(std::forward<Args>(args)...);
|
||||
|
@ -447,8 +461,8 @@ private:
|
|||
}
|
||||
|
||||
template<typename... Args>
|
||||
usertype(usertype_detail::verified_tag, Args&&... args) : indexfunc(nullptr), newindexfunc(nullptr), constructfunc(nullptr),
|
||||
destructfunc(nullptr), functiongcfunc(nullptr), needsindexfunction(false), baseclasscheck(nullptr), baseclasscast(nullptr) {
|
||||
usertype(usertype_detail::verified_tag, Args&&... args) : indexfunc(nullptr), newindexfunc(nullptr), constructfuncname(""), constructfunc(nullptr),
|
||||
destructfuncname(""), destructfunc(nullptr), functiongcfunc(nullptr), needsindexfunction(false), baseclasscheck(nullptr), baseclasscast(nullptr) {
|
||||
static_assert((sizeof...(Args) % 2) == 0, "Incorrect argument count to usertype creation: not in pairs. Might be missing name, function/property/variable, comma");
|
||||
functionnames.reserve(sizeof...(args)+3);
|
||||
functiontable.reserve(sizeof...(args)+3);
|
||||
|
@ -480,8 +494,15 @@ public:
|
|||
usertype_detail::push_metatable<detail::unique_usertype<T>, usertype_detail::stage::uniquemeta>(L, needsindexfunction, functions, functiontable, metafunctiontable, baseclasscheck, baseclasscast);
|
||||
lua_pop(L, 1);
|
||||
// but leave the regular T table on last
|
||||
// so it can be linked to a type for usage with `.new(...)` or `:new(...)`
|
||||
// so it can be linked to a key for usage with `.new(...)` or `:new(...)`
|
||||
usertype_detail::push_metatable<T, usertype_detail::stage::normalmeta>(L, needsindexfunction, functions, functiontable, metafunctiontable, baseclasscheck, baseclasscast);
|
||||
// be sure to link the construction function to allow for people to do the whole lua_bind thing
|
||||
if (constructfunc != nullptr && constructfuncname != nullptr && std::find(meta_function_names.cbegin(), meta_function_names.cend(), constructfuncname) != meta_function_names.cend()) {
|
||||
lua_createtable(L, 0, 0);
|
||||
sol::stack_table mt(L, -1);
|
||||
mt[constructfuncname] = constructfunc;
|
||||
lua_setmetatable(L, -2);
|
||||
}
|
||||
// Make sure to drop a table in the global namespace to properly destroy the pushed functions
|
||||
// at some later point in life
|
||||
usertype_detail::set_global_deleter<T>(L, functiongcfunc, functions);
|
||||
|
|
|
@ -272,6 +272,8 @@ TEST_CASE("tables/create-local-named", "Check if creating a table is kosher") {
|
|||
sol::table testtable = lua.create_table("testtable", 0, 0, "Woof", "Bark", 1, 2, 3, 4);
|
||||
sol::object testobj = lua["testtable"];
|
||||
REQUIRE(testobj.is<sol::table>());
|
||||
REQUIRE((testobj == testtable));
|
||||
REQUIRE_FALSE((testobj != testtable));
|
||||
REQUIRE((testtable["Woof"] == std::string("Bark")));
|
||||
REQUIRE((testtable[1] == 2));
|
||||
REQUIRE((testtable[3] == 4));
|
||||
|
|
54
tests.cpp
54
tests.cpp
|
@ -186,6 +186,13 @@ bool something() {
|
|||
return true;
|
||||
}
|
||||
|
||||
struct thing {
|
||||
int v = 100;
|
||||
|
||||
thing() {}
|
||||
thing(int x) : v(x) {}
|
||||
};
|
||||
|
||||
TEST_CASE("table/traversal", "ensure that we can chain requests and tunnel down into a value if we desire") {
|
||||
|
||||
sol::state lua;
|
||||
|
@ -935,8 +942,8 @@ TEST_CASE("usertype/readonly-and-static-functions", "Check if static functions c
|
|||
sol::meta_function::call_function, &bark::operator()
|
||||
);
|
||||
|
||||
lua.script("assert(bark.oh_boy('woo') == 3)");
|
||||
lua.script("bark.oh_boy()");
|
||||
REQUIRE_NOTHROW(lua.script("assert(bark.oh_boy('woo') == 3)"));
|
||||
REQUIRE_NOTHROW(lua.script("bark.oh_boy()"));
|
||||
|
||||
bark b;
|
||||
lua.set("b", &b);
|
||||
|
@ -1088,3 +1095,46 @@ TEST_CASE("utilities/this_state", "Ensure this_state argument can be gotten anyw
|
|||
REQUIRE(a == 625);
|
||||
REQUIRE(la == 625);
|
||||
}
|
||||
|
||||
TEST_CASE("usertype/call_constructor", "make sure lua types can be constructed with function call constructors") {
|
||||
sol::state lua;
|
||||
lua.open_libraries(sol::lib::base);
|
||||
|
||||
lua.new_usertype<thing>("thing",
|
||||
"v", &thing::v
|
||||
, sol::call_constructor, sol::constructors<sol::types<>, sol::types<int>>()
|
||||
);
|
||||
|
||||
lua.script(R"(
|
||||
t = thing(256)
|
||||
)");
|
||||
|
||||
thing& y = lua["t"];
|
||||
std::cout << y.v << std::endl;
|
||||
REQUIRE(y.v == 256);
|
||||
}
|
||||
|
||||
TEST_CASE("usertype/blank_constructor", "make sure lua types cannot be constructed if a blank / empty constructor is provided") {
|
||||
sol::state lua;
|
||||
lua.open_libraries(sol::lib::base);
|
||||
|
||||
lua.new_usertype<thing>("thing",
|
||||
"v", &thing::v
|
||||
, sol::call_constructor, sol::constructors<>()
|
||||
);
|
||||
|
||||
REQUIRE_THROWS(lua.script("t = thing(256)"));
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("usertype/no_constructor", "make sure lua types cannot be constructed if a blank / empty constructor is provided") {
|
||||
sol::state lua;
|
||||
lua.open_libraries(sol::lib::base);
|
||||
|
||||
lua.new_usertype<thing>("thing",
|
||||
"v", &thing::v
|
||||
, sol::call_constructor, sol::no_constructor
|
||||
);
|
||||
|
||||
REQUIRE_THROWS(lua.script("t = thing.new()"));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user