primer::bound_function is a primer::lua_ref
which is known to point to an object of function type.
bound_function provides
several handy methods for calling the function, passing in one or several
C++ objects, and obtaining the result as (one or several) primer::lua_ref. These objects are pushed onto
the lua stack using primer::push,
then the bound function is invoked using pcall. Any errors are returned
to the caller -- the lua stack is always unchanged by this operation at
the end.
primer::bound_function can be used to create
C++ function objects referring to a function implemented in lua.
These objects are safe -- calling them
does not raise exceptions, and they handle any lua errors and return them
as primer::error objects, even if the user function
errs or the lua VM is destroyed. Furthermore, they carry out an appropriate
call to lua_checkstack
no matter what parameters they are passed for the call.
The idea is that you should be able to pass these to other parts of a C++ program that don't have anything to do with lua, and use them like generic function objects without having to mentally switch context and think about lua preconditions and such.
![]() |
Caution |
|---|---|
Like |
primer::bound_function can also be used to create
a primer::coroutine.
class bound_function { lua_ref ref_; public: // Special member functions bound_function() noexcept = default; bound_function(const bound_function &) = default; bound_function(bound_function &&) noexcept = default; bound_function & operator=(const bound_function &) = default; bound_function & operator=(bound_function &&) noexcept = default; ~bound_function() noexcept = default; // Primary constructor: Bind to a function on top of the stack. // Only capture the top item if it is actually a function. // Pop the item *whether or not* it is a function.explicit bound_function(lua_State * L); // Forwarded methods from lua_ref explicit operator bool() const noexcept { return static_cast<bool>(ref_); } lua_State * lock() const noexcept { return ref_.lock(); } lua_State * push() const noexcept { return ref_.push(); } bool push(lua_State * L) const noexcept { return ref_.push(L); } void reset() noexcept { ref_.reset(); } void swap(bound_function & other) noexcept { ref_.swap(other.ref_); } // Call methods // These methods attempt to lock the state which holds the lua function, // and perform the call there. They clean up after themselves and leave the // stack as they found it afterwards. // // If passed a lua_ref_seq, its members are the call arguments. If passed // any other sequence of C++ types, those objects are pushed onto the stack // and are the call arguments. template <typename... Args> expected<void> call_no_ret(Args &&... args) const noexcept; expected<void> call_no_ret(lua_ref_seq &) const noexcept; expected<void> call_no_ret(lua_ref_seq const &) const noexcept; expected<void> call_no_ret(lua_ref_seq &&) const noexcept; template <typename... Args> expected<lua_ref> call_one_ret(Args &&... args) const noexcept; expected<lua_ref> call_one_ret(lua_ref_seq &) const noexcept; expected<lua_ref> call_one_ret(lua_ref_seq const &) const noexcept; expected<lua_ref> call_one_ret(lua_ref_seq &&) const noexcept; template <typename... Args> expected<lua_ref_seq> call(Args &&... args) const noexcept; expected<lua_ref_seq> call(lua_ref_seq &) const noexcept; expected<lua_ref_seq> call(lua_ref_seq const &) const noexcept; expected<lua_ref_seq> call(lua_ref_seq &&) const noexcept; // Get a debug string describing what function is bound // Uses lua debug api std::string debug_string() const; };
Similar to lua_ref, these
can be pushed onto the stack by primer::push.
On read, the nil value is read as putting the bound_function
into the empty state. Otherwise, if it's a function, it is bound, and anything
else causes an error.