]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/leaf/examples/lua_callback_eh.cpp
1 // Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc.
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 // This is a simple program that shows how to report error objects out of a
7 // C-callback that happens to be C++-exception safe.
13 #include <boost/leaf/handle_errors.hpp>
14 #include <boost/leaf/exception.hpp>
15 #include <boost/leaf/on_error.hpp>
19 namespace leaf
= boost::leaf
;
21 enum do_work_error_code
27 struct e_lua_pcall_error
{ int value
; };
28 struct e_lua_error_message
{ std::string value
; };
31 // This is a C callback with a specific signature, callable from programs written in Lua.
32 // If it succeeds, it returns an int answer, by pushing it onto the Lua stack. But "sometimes"
33 // it fails, in which case it throws an exception. This causes the Lua interpreter to abort and
34 // pop back into the C++ code which called it (see call_lua below).
35 int do_work( lua_State
* L
)
37 bool success
= rand()%2; // "Sometimes" do_work fails.
40 lua_pushnumber(L
, 42); // Success, push the result on the Lua stack, return to Lua.
45 throw leaf::exception(ec1
);
50 std::shared_ptr
<lua_State
> init_lua_state()
52 // Create a new lua_State, we'll use std::shared_ptr for automatic cleanup.
53 std::shared_ptr
<lua_State
> L(lua_open(), &lua_close
);
55 // Register the do_work function (above) as a C callback, under the global
56 // Lua name "do_work". With this, calls from Lua programs to do_work
57 // will land in the do_work C function we've registered.
58 lua_register( &*L
, "do_work", &do_work
);
60 // Pass some Lua code as a C string literal to Lua. This creates a global Lua
61 // function called "call_do_work", which we will later ask Lua to execute.
62 luaL_dostring( &*L
, "\
63 \n function call_do_work()\
71 // Here we will ask Lua to execute the function call_do_work, which is written
72 // in Lua, and returns the value from do_work, which is written in C++ and
73 // registered with the Lua interpreter as a C callback.
75 // If do_work succeeds, we return the resulting int answer.
76 // If it fails, we'll communicate that failure to our caller.
77 int call_lua( lua_State
* L
)
79 // Ask the Lua interpreter to call the global Lua function call_do_work.
80 lua_getfield( L
, LUA_GLOBALSINDEX
, "call_do_work" );
81 if( int err
= lua_pcall(L
, 0, 1, 0) ) // Ask Lua to call the global function call_do_work.
83 auto load
= leaf::on_error(e_lua_error_message
{lua_tostring(L
, 1)});
86 // We got a Lua error that is definitely not the error we're throwing in do_work.
87 // (if it did throw an exception, we won't be here).
88 // Throw a new exception to indicate that lua_pcall returned an error.
89 throw leaf::exception(e_lua_pcall_error
{err
});
93 // Success! Just return the int answer.
94 int answer
=lua_tonumber(L
, -1);
102 std::shared_ptr
<lua_State
> L
=init_lua_state();
104 for( int i
=0; i
!=10; ++i
)
110 int answer
= call_lua(&*L
);
111 std::cout
<< "do_work succeeded, answer=" << answer
<< '\n';
115 []( do_work_error_code e
)
117 std::cout
<< "Got do_work_error_code = " << e
<< "!\n";
120 []( e_lua_pcall_error
const & err
, e_lua_error_message
const & msg
)
122 std::cout
<< "Got e_lua_pcall_error, Lua error code = " << err
.value
<< ", " << msg
.value
<< "\n";
125 []( leaf::error_info
const & unmatched
)
128 "Unknown failure detected" << std::endl
<<
129 "Cryptic diagnostic information follows" << std::endl
<<