mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
ability for functions that throw not bound by sol to catch and return lua errors that can be used by a handler function (for protected function).
This commit is contained in:
parent
6c070661a7
commit
923c774d5e
|
@ -131,7 +131,7 @@ script:
|
|||
- echo "Configuration info:"
|
||||
- export_compiler_vars
|
||||
- ninja --version
|
||||
- ./bootstrap.py --ci && ninja
|
||||
- ./bootstrap.py --ci && ninja && ninja examples
|
||||
|
||||
notifications:
|
||||
email:
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include <sol.hpp>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
|
||||
inline int my_add(int x, int y) {
|
||||
return x + y;
|
||||
|
@ -46,17 +47,27 @@ int main() {
|
|||
// calling a stateful lambda modifies the value
|
||||
lua.script("inc()");
|
||||
assert(x == 10);
|
||||
if (x == 10) {
|
||||
// Do something based on this information
|
||||
std::cout << "Yahoo!" << std::endl;
|
||||
}
|
||||
|
||||
// this can be done as many times as you want
|
||||
lua.script("inc()\ninc()\ninc()");
|
||||
assert(x == 40);
|
||||
|
||||
if (x == 40) {
|
||||
// Do something based on this information
|
||||
std::cout << "Yahoo!" << std::endl;
|
||||
}
|
||||
// retrieval of a function is done similarly
|
||||
// to other variables, using sol::function
|
||||
sol::function add = lua["my_add"];
|
||||
int value = add(10, 11);
|
||||
assert(add.call<int>(10, 11) == 21);
|
||||
assert(value == 21);
|
||||
if (value == 21) {
|
||||
std::cout << "Woo, it's 21!" << std::endl;
|
||||
}
|
||||
|
||||
// multi-return functions are supported using
|
||||
// std::tuple as the interface.
|
||||
|
@ -76,8 +87,7 @@ int main() {
|
|||
// you can even overload functions
|
||||
// just pass in the different functions
|
||||
// you want to pack into a single name:
|
||||
// make SURE they take different number of
|
||||
// arguments/different types!
|
||||
// make SURE they take different types!
|
||||
|
||||
lua.set_function("func", sol::overload([](int x) { return x; }, make_string, my_add));
|
||||
|
||||
|
|
|
@ -18,9 +18,6 @@ int main() {
|
|||
"}");
|
||||
|
||||
|
||||
auto t2 = lua.get<sol::table>("table2");
|
||||
auto nestedTable = t2.get<sol::table>("nestedTable");
|
||||
|
||||
/* Shorter Syntax: */
|
||||
// using the values stored in table1
|
||||
/*std::cout << (std::string)lua["table1"][1] << " "
|
||||
|
@ -29,18 +26,19 @@ int main() {
|
|||
// some retrieval of values from the nested table
|
||||
// the cleaner way of doing things
|
||||
// chain off the the get<>() / [] results
|
||||
auto t2 = lua.get<sol::table>("table2");
|
||||
auto nestedTable = t2.get<sol::table>("nestedTable");
|
||||
// Alternatively:
|
||||
//sol::table t2 = lua["table2"];
|
||||
//sol::table nestedTable = t2["nestedTable"];
|
||||
|
||||
std::string x = lua["table2"]["nestedTable"]["key2"];
|
||||
std::cout << "nested table: key1 : " << nestedTable.get<std::string>("key1") << ", key2: "
|
||||
<< x
|
||||
<< '\n';
|
||||
std::cout << "name of t2: " << t2.get<std::string>("name") << '\n';
|
||||
#ifndef _MSC_VER
|
||||
// VC++ has a bug in its implementation and
|
||||
// I've filed a bug against the compiler at Microsoft,
|
||||
// but the following
|
||||
// works on g++ and clang++
|
||||
std::cout << "name of t2: " << (std::string)t2["name"] << '\n';
|
||||
#endif // VC++ being a dumb
|
||||
std::string t2name = t2["name"];
|
||||
std::cout << "name of t2: " << t2name << '\n';
|
||||
|
||||
/* Longer Syntax: */
|
||||
// using the values stored in table1
|
||||
|
|
|
@ -60,7 +60,7 @@ int main() {
|
|||
"y = x:test(10)");
|
||||
|
||||
auto y = lua.get<int>("y");
|
||||
assert(y == 14);
|
||||
std::cout << y << std::endl; // show 14
|
||||
|
||||
// if you want a class to have more than one constructor
|
||||
// the way to do so is through set_userdata and creating
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#include <sol.hpp>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
|
||||
int main() {
|
||||
sol::state lua;
|
||||
|
@ -26,9 +26,9 @@ int main() {
|
|||
std::string y2;
|
||||
std::tie(x2, y2) = lua.get<int, std::string>("x", "y");
|
||||
|
||||
// assert the values
|
||||
assert(x == 10);
|
||||
assert(y == "hello");
|
||||
assert(x2 == 10);
|
||||
assert(y2 == "hello");
|
||||
// show the values
|
||||
std::cout << x << std::endl;
|
||||
std::cout << y << std::endl;
|
||||
std::cout << x2 << std::endl;
|
||||
std::cout << y2 << std::endl;
|
||||
}
|
|
@ -163,26 +163,33 @@ private:
|
|||
int firstreturn = std::max(1, stacksize - static_cast<int>(n) - 1);
|
||||
int returncount = 0;
|
||||
call_status code = call_status::ok;
|
||||
#ifdef SOL_NO_EXCEPTIONS
|
||||
code = static_cast<call_status>(luacall(n, LUA_MULTRET, h));
|
||||
int poststacksize = lua_gettop(lua_state());
|
||||
returncount = poststacksize - firstreturn;
|
||||
#else
|
||||
#ifndef SOL_NO_EXCEPTIONS
|
||||
auto onexcept = [&](const char* error) {
|
||||
h.stackindex = 0;
|
||||
if (h.target.valid()) {
|
||||
h.target.push();
|
||||
stack::push(lua_state(), error);
|
||||
lua_call(lua_state(), 1, 1);
|
||||
}
|
||||
else {
|
||||
stack::push(lua_state(), error);
|
||||
}
|
||||
};
|
||||
try {
|
||||
#endif // No Exceptions
|
||||
code = static_cast<call_status>(luacall(n, LUA_MULTRET, h));
|
||||
int poststacksize = lua_gettop(lua_state());
|
||||
returncount = poststacksize - firstreturn;
|
||||
#ifndef SOL_NO_EXCEPTIONS
|
||||
}
|
||||
// Handle C++ errors thrown from C++ functions bound inside of lua
|
||||
catch (const char* error) {
|
||||
h.stackindex = 0;
|
||||
stack::push(lua_state(), error);
|
||||
onexcept(error);
|
||||
firstreturn = lua_gettop(lua_state());
|
||||
return protected_function_result(lua_state(), firstreturn, 0, 1, call_status::runtime);
|
||||
}
|
||||
catch (const std::exception& error) {
|
||||
h.stackindex = 0;
|
||||
stack::push(lua_state(), error.what());
|
||||
onexcept(error.what());
|
||||
firstreturn = lua_gettop(lua_state());
|
||||
return protected_function_result(lua_state(), firstreturn, 0, 1, call_status::runtime);
|
||||
}
|
||||
|
@ -347,7 +354,7 @@ struct pusher<function_sig<Sigs...>> {
|
|||
template<typename... Args>
|
||||
static int push(lua_State* L, Args&&... args) {
|
||||
// Set will always place one thing (function) on the stack
|
||||
set(L, std::forward<Args>(args)...);
|
||||
set<Sigs...>(L, std::forward<Args>(args)...);
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -35,8 +35,6 @@ public:
|
|||
template<typename T>
|
||||
decltype(auto) as() const {
|
||||
push();
|
||||
type actual = stack::get<type>(lua_state());
|
||||
type_assert(lua_state(), -1, type_of<T>(), actual);
|
||||
return stack::pop<T>(lua_state());
|
||||
}
|
||||
|
||||
|
|
|
@ -313,10 +313,7 @@ struct getter<const char*> {
|
|||
|
||||
template<>
|
||||
struct getter<nil_t> {
|
||||
static nil_t get(lua_State* L, int index = -1) {
|
||||
if(lua_isnil(L, index) == 0) {
|
||||
throw error("not nil");
|
||||
}
|
||||
static nil_t get(lua_State*, int = -1) {
|
||||
return nil_t{ };
|
||||
}
|
||||
};
|
||||
|
@ -869,7 +866,6 @@ inline int call_into_lua(types<Ret0, Ret...>, types<Args...> ta, Fx&& fx, lua_St
|
|||
}
|
||||
|
||||
inline call_syntax get_call_syntax(lua_State* L, const std::string& meta) {
|
||||
type metatype = stack::get<type>(L);
|
||||
luaL_getmetatable(L, meta.c_str());
|
||||
if (lua_compare(L, -1, -2, LUA_OPEQ) == 1) {
|
||||
lua_pop(L, 1);
|
||||
|
|
|
@ -29,9 +29,13 @@
|
|||
namespace sol {
|
||||
namespace detail {
|
||||
inline int atpanic(lua_State* L) {
|
||||
#ifdef SOL_NO_EXCEPTIONS
|
||||
(void)L;
|
||||
#else
|
||||
const char* message = lua_tostring(L, -1);
|
||||
std::string err = message ? message : "An unexpected error occurred and forced the lua state to call atpanic";
|
||||
throw error(err);
|
||||
#endif
|
||||
}
|
||||
} // detail
|
||||
|
||||
|
|
|
@ -237,7 +237,7 @@ private:
|
|||
// Insert bubble to keep with compile-time argument count (simpler and cheaper to do)
|
||||
functions.push_back(nullptr);
|
||||
constructfunc = function_detail::construct<T, Args...>;
|
||||
metafunctiontable.push_back({ functionnames.back().c_str(), constructfunc });
|
||||
metafunctiontable.push_back({ name.c_str(), constructfunc });
|
||||
}
|
||||
|
||||
template<std::size_t N>
|
||||
|
|
12
tests.cpp
12
tests.cpp
|
@ -1193,12 +1193,16 @@ TEST_CASE( "functions/function_result-protected_function_result", "Function resu
|
|||
+ "end"
|
||||
);
|
||||
|
||||
lua.set("nontrampoline", (lua_CFunction)[](lua_State*) -> int { throw "x";});
|
||||
|
||||
sol::protected_function doom = lua[ "doom" ];
|
||||
sol::protected_function luadoom = lua["luadoom"];
|
||||
sol::protected_function nontrampoline = lua["nontrampoline"];
|
||||
sol::function luahandler = lua["luahandler"];
|
||||
sol::function cpphandler = lua[ "cpphandler" ];
|
||||
doom.error_handler = luahandler;
|
||||
luadoom.error_handler = cpphandler;
|
||||
nontrampoline.error_handler = cpphandler;
|
||||
|
||||
{
|
||||
sol::protected_function_result result = doom();
|
||||
|
@ -1212,6 +1216,12 @@ TEST_CASE( "functions/function_result-protected_function_result", "Function resu
|
|||
std::string errorstring = result;
|
||||
REQUIRE(errorstring == handlederrormessage);
|
||||
}
|
||||
{
|
||||
sol::protected_function_result result = nontrampoline();
|
||||
REQUIRE(!result.valid());
|
||||
std::string errorstring = result;
|
||||
REQUIRE(errorstring == handlederrormessage);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("functions/destructor-tests", "Show that proper copies / destruction happens") {
|
||||
|
@ -1289,7 +1299,7 @@ TEST_CASE("functions/destructor-tests", "Show that proper copies / destruction h
|
|||
REQUIRE(last_call == static_call);
|
||||
}
|
||||
REQUIRE(created == 1);
|
||||
REQUIRE(destroyed == 2);
|
||||
REQUIRE(destroyed == 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user