Skip to content

Commit 2cfbc8c

Browse files
committed
Fix up the remaining sol2 issues, prepare for more sol3 stuff
1 parent a7048ae commit 2cfbc8c

File tree

9 files changed

+122
-33
lines changed

9 files changed

+122
-33
lines changed

docs/source/api/proxy.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,17 @@ Gets the value associated with the keys and converts it to the type ``T``.
7878

7979
Gets the value associated with the keys and converts it to the type ``T``. If it is not of the proper type, it will return a ``sol::nullopt`` instead.
8080

81+
.. code-block:: c++
82+
:caption: function: [overloaded] optionally get or create a value
83+
:name: regular-get-or-create
84+
85+
template <typename T>
86+
decltype(auto) get_or_create();
87+
template <typename T, typename Otherwise>
88+
decltype(auto) get_or_create( Otherwise&& other );
89+
90+
Gets the value associated with the keys if it exists. If it does not, it will set it with the value and return the result.
91+
8192
``operator[]`` proxy-only members
8293
---------------------------------
8394

examples/tutorials/quick_n_dirty/namespacing.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,14 @@ int main() {
2424

2525
// "bark" namespacing in Lua
2626
// namespacing is just putting things in a table
27-
sol::table bark = lua.create_named_table("bark");
27+
// forces creation if it does not exist
28+
auto bark = lua["bark"].get_or_create<sol::table>();
29+
// equivalent-ish:
30+
//sol::table bark = lua["bark"].force(); // forces table creation
31+
// equivalent, and more flexible:
32+
//sol::table bark = lua["bark"].get_or_create<sol::table>(sol::new_table());
33+
// equivalent, but less efficient/ugly:
34+
//sol::table bark = lua["bark"] = lua.get_or("bark", lua.create_table());
2835
bark.new_usertype<my_class>("my_class",
2936
"f", &my_class::f,
3037
"g", &my_class::g); // the usual

single/sol/sol.hpp

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@
2020
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2121

2222
// This file was generated with a script.
23-
// Generated 2018-11-09 18:52:51.075276 UTC
24-
// This header was generated with sol v2.20.4 (revision 1f90b04)
23+
// Generated 2018-11-10 14:40:45.361811 UTC
24+
// This header was generated with sol v2.20.5 (revision a7048ae)
2525
// https://github.com/ThePhD/sol2
2626

2727
#ifndef SOL_SINGLE_INCLUDE_HPP
@@ -8247,12 +8247,12 @@ namespace stack {
82478247
}
82488248
#endif // Do not allow strings to be numbers
82498249
int isnum = 0;
8250-
const lua_Number v = lua_tonumberx(L, index, &isnum);
8251-
const bool success = isnum != 0
82528250
#if (defined(SOL_SAFE_NUMERICS) && SOL_SAFE_NUMERICS) && !(defined(SOL_NO_CHECK_NUMBER_PRECISION) && SOL_NO_CHECK_NUMBER_PRECISION)
8253-
&& static_cast<lua_Number>(llround(v)) == v
8251+
const lua_Number v = lua_tonumberx(L, index, &isnum);
8252+
const bool success = isnum != 0 && static_cast<lua_Number>(llround(v)) == v;
8253+
#else
8254+
const bool success = isnum != 0;
82548255
#endif // Safe numerics and number precision checking
8255-
;
82568256
if (!success) {
82578257
// expected type, actual type
82588258
#if defined(SOL_STRINGS_ARE_NUMBERS) && SOL_STRINGS_ARE_NUMBERS
@@ -14542,7 +14542,7 @@ namespace sol {
1454214542

1454314543
template <bool is_yielding, typename Fx, typename... Args>
1454414544
static void set_fx(lua_State* L, Args&&... args) {
14545-
lua_CFunction freefunc = function_detail::call<meta::unqualified_t<Fx>, 2, is_yielding>;
14545+
lua_CFunction freefunc = detail::static_trampoline<function_detail::call<meta::unqualified_t<Fx>, 2, is_yielding>>;
1454614546

1454714547
int upvalues = 0;
1454814548
upvalues += stack::push(L, nullptr);
@@ -15512,6 +15512,19 @@ namespace sol {
1551215512
return static_cast<T>(std::forward<D>(otherwise));
1551315513
}
1551415514

15515+
template <typename T>
15516+
decltype(auto) get_or_create() {
15517+
return get_or_create<T>(new_table());
15518+
}
15519+
15520+
template <typename T, typename Otherwise>
15521+
decltype(auto) get_or_create(Otherwise&& other) {
15522+
if (!this->valid()) {
15523+
this->set(std::forward<Otherwise>(other));
15524+
}
15525+
return get<T>();
15526+
}
15527+
1551515528
template <typename K>
1551615529
decltype(auto) operator[](K&& k) const {
1551715530
auto keys = meta::tuplefy(key, std::forward<K>(k));
@@ -15562,6 +15575,13 @@ namespace sol {
1556215575
lua_State* lua_state() const {
1556315576
return tbl.lua_state();
1556415577
}
15578+
15579+
proxy& force() {
15580+
if (this->valid()) {
15581+
this->set(new_table());
15582+
}
15583+
return *this;
15584+
}
1556515585
};
1556615586

1556715587
template <typename Table, typename Key, typename T>
@@ -18280,6 +18300,9 @@ namespace sol {
1828018300
#include <bitset>
1828118301

1828218302
namespace sol {
18303+
18304+
struct usertype_metatable_core;
18305+
1828318306
namespace usertype_detail {
1828418307
const int metatable_index = 2;
1828518308
const int metatable_core_index = 3;
@@ -18291,7 +18314,7 @@ namespace sol {
1829118314
const int newindex_function_index = 4;
1829218315

1829318316
typedef void (*base_walk)(lua_State*, bool&, int&, string_view&);
18294-
typedef int (*member_search)(lua_State*, void*, int);
18317+
typedef int (*member_search)(lua_State*, void*, usertype_metatable_core&, int);
1829518318

1829618319
struct call_information {
1829718320
member_search index;
@@ -18443,8 +18466,7 @@ namespace sol {
1844318466
return isnum != 0 && magic == toplevel_magic;
1844418467
}
1844518468

18446-
inline int runtime_object_call(lua_State* L, void*, int runtimetarget) {
18447-
usertype_metatable_core& umc = stack::get<light<usertype_metatable_core>>(L, upvalue_index(metatable_core_index));
18469+
inline int runtime_object_call(lua_State* L, void*, usertype_metatable_core& umc, int runtimetarget) {
1844818470
std::vector<object>& runtime = umc.runtime;
1844918471
object& runtimeobj = runtime[runtimetarget];
1845018472
return stack::push(L, runtimeobj);
@@ -18476,7 +18498,7 @@ namespace sol {
1847618498
}
1847718499
}
1847818500

18479-
int runtime_new_index(lua_State* L, void*, int runtimetarget);
18501+
int runtime_new_index(lua_State* L, void*, usertype_metatable_core&, int runtimetarget);
1848018502

1848118503
template <typename T, bool is_simple>
1848218504
inline int metatable_new_index(lua_State* L) {
@@ -18575,8 +18597,7 @@ namespace sol {
1857518597
return indexing_fail<T, false>(L);
1857618598
}
1857718599

18578-
inline int runtime_new_index(lua_State* L, void*, int runtimetarget) {
18579-
usertype_metatable_core& umc = stack::get<light<usertype_metatable_core>>(L, upvalue_index(metatable_core_index));
18600+
inline int runtime_new_index(lua_State* L, void*, usertype_metatable_core& umc, int runtimetarget) {
1858018601
std::vector<object>& runtime = umc.runtime;
1858118602
object& runtimeobj = runtime[runtimetarget];
1858218603
runtimeobj = object(L, 3);
@@ -18781,7 +18802,7 @@ namespace sol {
1878118802
usertype_metatable& operator=(usertype_metatable&&) = default;
1878218803

1878318804
template <std::size_t I0, std::size_t I1, bool is_index>
18784-
static int real_find_call(lua_State* L, void* um, int) {
18805+
static int real_find_call(lua_State* L, void* um, usertype_metatable_core&, int) {
1878518806
auto& f = *static_cast<usertype_metatable*>(um);
1878618807
if (is_variable_binding<decltype(std::get<I1>(f.functions))>::value) {
1878718808
return real_call_with<I1, is_index, true>(L, f);
@@ -18827,7 +18848,7 @@ namespace sol {
1882718848
}
1882818849
}
1882918850
if (member != nullptr) {
18830-
return (member)(L, static_cast<void*>(&f), runtime_target);
18851+
return (member)(L, static_cast<void*>(&f), static_cast<usertype_metatable_core&>(f), runtime_target);
1883118852
}
1883218853
string_view accessor = stack::get<string_view>(L, keyidx);
1883318854
int ret = 0;

single/sol/sol_forward.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@
2020
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2121

2222
// This file was generated with a script.
23-
// Generated 2018-11-09 18:52:51.285820 UTC
24-
// This header was generated with sol v2.20.4 (revision 1f90b04)
23+
// Generated 2018-11-10 14:40:45.917037 UTC
24+
// This header was generated with sol v2.20.5 (revision a7048ae)
2525
// https://github.com/ThePhD/sol2
2626

2727
#ifndef SOL_SINGLE_INCLUDE_FORWARD_HPP

sol/function_types.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ namespace sol {
220220

221221
template <bool is_yielding, typename Fx, typename... Args>
222222
static void set_fx(lua_State* L, Args&&... args) {
223-
lua_CFunction freefunc = function_detail::call<meta::unqualified_t<Fx>, 2, is_yielding>;
223+
lua_CFunction freefunc = detail::static_trampoline<function_detail::call<meta::unqualified_t<Fx>, 2, is_yielding>>;
224224

225225
int upvalues = 0;
226226
upvalues += stack::push(L, nullptr);

sol/proxy.hpp

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// sol2
1+
// sol2
22

33
// The MIT License (MIT)
44

@@ -118,6 +118,20 @@ namespace sol {
118118
return static_cast<T>(std::forward<D>(otherwise));
119119
}
120120

121+
122+
template <typename T>
123+
decltype(auto) get_or_create() {
124+
return get_or_create<T>(new_table());
125+
}
126+
127+
template <typename T, typename Otherwise>
128+
decltype(auto) get_or_create(Otherwise&& other) {
129+
if (!this->valid()) {
130+
this->set(std::forward<Otherwise>(other));
131+
}
132+
return get<T>();
133+
}
134+
121135
template <typename K>
122136
decltype(auto) operator[](K&& k) const {
123137
auto keys = meta::tuplefy(key, std::forward<K>(k));
@@ -168,6 +182,13 @@ namespace sol {
168182
lua_State* lua_state() const {
169183
return tbl.lua_state();
170184
}
185+
186+
proxy& force() {
187+
if (this->valid()) {
188+
this->set(new_table());
189+
}
190+
return *this;
191+
}
171192
};
172193

173194
template <typename Table, typename Key, typename T>

sol/stack_check_unqualified.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -140,12 +140,12 @@ namespace stack {
140140
}
141141
#endif // Do not allow strings to be numbers
142142
int isnum = 0;
143-
const lua_Number v = lua_tonumberx(L, index, &isnum);
144-
const bool success = isnum != 0
145143
#if (defined(SOL_SAFE_NUMERICS) && SOL_SAFE_NUMERICS) && !(defined(SOL_NO_CHECK_NUMBER_PRECISION) && SOL_NO_CHECK_NUMBER_PRECISION)
146-
&& static_cast<lua_Number>(llround(v)) == v
144+
const lua_Number v = lua_tonumberx(L, index, &isnum);
145+
const bool success = isnum != 0 && static_cast<lua_Number>(llround(v)) == v;
146+
#else
147+
const bool success = isnum != 0;
147148
#endif // Safe numerics and number precision checking
148-
;
149149
if (!success) {
150150
// expected type, actual type
151151
#if defined(SOL_STRINGS_ARE_NUMBERS) && SOL_STRINGS_ARE_NUMBERS

sol/usertype_metatable.hpp

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@
4343
#include <bitset>
4444

4545
namespace sol {
46+
47+
struct usertype_metatable_core;
48+
4649
namespace usertype_detail {
4750
const int metatable_index = 2;
4851
const int metatable_core_index = 3;
@@ -54,7 +57,7 @@ namespace sol {
5457
const int newindex_function_index = 4;
5558

5659
typedef void (*base_walk)(lua_State*, bool&, int&, string_view&);
57-
typedef int (*member_search)(lua_State*, void*, int);
60+
typedef int (*member_search)(lua_State*, void*, usertype_metatable_core&, int);
5861

5962
struct call_information {
6063
member_search index;
@@ -206,8 +209,7 @@ namespace sol {
206209
return isnum != 0 && magic == toplevel_magic;
207210
}
208211

209-
inline int runtime_object_call(lua_State* L, void*, int runtimetarget) {
210-
usertype_metatable_core& umc = stack::get<light<usertype_metatable_core>>(L, upvalue_index(metatable_core_index));
212+
inline int runtime_object_call(lua_State* L, void*, usertype_metatable_core& umc, int runtimetarget) {
211213
std::vector<object>& runtime = umc.runtime;
212214
object& runtimeobj = runtime[runtimetarget];
213215
return stack::push(L, runtimeobj);
@@ -239,7 +241,7 @@ namespace sol {
239241
}
240242
}
241243

242-
int runtime_new_index(lua_State* L, void*, int runtimetarget);
244+
int runtime_new_index(lua_State* L, void*, usertype_metatable_core&, int runtimetarget);
243245

244246
template <typename T, bool is_simple>
245247
inline int metatable_new_index(lua_State* L) {
@@ -338,8 +340,7 @@ namespace sol {
338340
return indexing_fail<T, false>(L);
339341
}
340342

341-
inline int runtime_new_index(lua_State* L, void*, int runtimetarget) {
342-
usertype_metatable_core& umc = stack::get<light<usertype_metatable_core>>(L, upvalue_index(metatable_core_index));
343+
inline int runtime_new_index(lua_State* L, void*, usertype_metatable_core& umc, int runtimetarget) {
343344
std::vector<object>& runtime = umc.runtime;
344345
object& runtimeobj = runtime[runtimetarget];
345346
runtimeobj = object(L, 3);
@@ -544,7 +545,7 @@ namespace sol {
544545
usertype_metatable& operator=(usertype_metatable&&) = default;
545546

546547
template <std::size_t I0, std::size_t I1, bool is_index>
547-
static int real_find_call(lua_State* L, void* um, int) {
548+
static int real_find_call(lua_State* L, void* um, usertype_metatable_core&, int) {
548549
auto& f = *static_cast<usertype_metatable*>(um);
549550
if (is_variable_binding<decltype(std::get<I1>(f.functions))>::value) {
550551
return real_call_with<I1, is_index, true>(L, f);
@@ -590,7 +591,7 @@ namespace sol {
590591
}
591592
}
592593
if (member != nullptr) {
593-
return (member)(L, static_cast<void*>(&f), runtime_target);
594+
return (member)(L, static_cast<void*>(&f), static_cast<usertype_metatable_core&>(f), runtime_target);
594595
}
595596
string_view accessor = stack::get<string_view>(L, keyidx);
596597
int ret = 0;

tests/test_usertypes.cpp

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ struct alignas(16) weird_aligned_wrapper {
310310
}
311311
void operator()(SelfType& self, sol::object param) const {
312312
lambda(self, param.as<float>());
313-
}
313+
}
314314
std::function<void(SelfType&, float)> lambda;
315315
};
316316

@@ -1627,6 +1627,16 @@ TEST_CASE("usertype/runtime-extensibility", "Check if usertypes are runtime exte
16271627
};
16281628
int val = 0;
16291629

1630+
class base_a {
1631+
public:
1632+
int x;
1633+
};
1634+
1635+
class derived_b : public base_a {
1636+
};
1637+
1638+
1639+
16301640
SECTION("just functions") {
16311641
sol::state lua;
16321642
lua.open_libraries(sol::lib::base);
@@ -1722,6 +1732,24 @@ end
17221732
val = lua["val"];
17231733
REQUIRE(val == 3);
17241734
}
1735+
SECTION("with bases") {
1736+
sol::state lua;
1737+
lua.open_libraries(sol::lib::base);
1738+
1739+
lua.new_usertype<base_a>("A",
1740+
"x", &base_a::x //no crash without this
1741+
);
1742+
1743+
lua.new_usertype<derived_b>("B",
1744+
sol::base_classes, sol::bases<base_a>());
1745+
1746+
auto pfr0 = lua.safe_script("function A:c() print('A') return 1 end", sol::script_pass_on_error);
1747+
REQUIRE(pfr0.valid());
1748+
auto pfr1 = lua.safe_script("function B:c() print('B') return 2 end", sol::script_pass_on_error);
1749+
REQUIRE(pfr1.valid());
1750+
auto pfr2 = lua.safe_script("local obja = A.new() local objb = B.new() assert(obja:c() == 1) assert(objb:c() == 2)", sol::script_pass_on_error);
1751+
REQUIRE(pfr2.valid());
1752+
}
17251753
}
17261754

17271755
TEST_CASE("usertype/runtime-replacement", "ensure that functions can be properly replaced at runtime for non-indexed things") {

0 commit comments

Comments
 (0)