sol2/examples/custom_global_transparent_argument.cpp
2018-03-09 23:40:37 -05:00

75 lines
2.0 KiB
C++

#define SOL_CHECK_ARGUMENTS 1
#include <sol.hpp>
// Something that can't be collided with
constexpr static const auto& script_key = "GlobalResource.MySpecialIdentifier123";
struct GlobalResource {
int value = 2;
};
// Customize sol2 to handle this type
namespace sol {
template <>
struct lua_type_of<GlobalResource*> : std::integral_constant<sol::type, sol::type::lightuserdata> {};
namespace stack {
template <>
struct checker<GlobalResource*> {
template <typename Handler>
static bool check(lua_State* L, int /*index*/, Handler&& handler, record& tracking) {
tracking.use(0);
// get the field from global storage
stack::get_field<true>(L, script_key);
// verify type
type t = static_cast<type>(lua_type(L, -1));
lua_pop(L, 1);
if (t != type::lightuserdata) {
handler(L, 0, type::lightuserdata, t, "global resource is not present");
return false;
}
return true;
}
};
template <>
struct getter<GlobalResource*> {
static GlobalResource* get(lua_State* L, int /*index*/, record& tracking) {
// retrieve the (light) userdata for this type
tracking.use(0); // not actually pulling anything off the stack
stack::get_field<true>(L, script_key);
GlobalResource* ls = static_cast<GlobalResource*>(lua_touserdata(L, -1));
lua_pop(L, 1); // clean up stack value returned by `get_field`
return ls;
};
};
template <>
struct pusher<GlobalResource*> {
static int push(lua_State* L, GlobalResource* ls) {
// push light userdata
return stack::push(L, make_light(ls));;
}
};
}
}
int main() {
sol::state lua;
lua.open_libraries(sol::lib::base);
GlobalResource instance;
// get GlobalResource
lua.set_function("f", [](GlobalResource* l, int value) {
return l->value + value;
});
lua.set(script_key, &instance);
// note only 1 argument,
// despite being 2
lua.script("assert(f(1) == 3)");
return 0;
}