fix method bind
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
|
||||
#include <mruby/class.h>
|
||||
#include <mruby/data.h>
|
||||
#include <mruby/proc.h>
|
||||
|
||||
template <typename... Args, size_t... Is>
|
||||
std::tuple<Args...> mrubypp_get_args_helper_impl(mrb_state *mrb,
|
||||
@@ -40,15 +41,19 @@ mrubypp_get_args_helper(mrb_state *mrb) {
|
||||
|
||||
template <typename T, typename Ret, typename... MethodArgs>
|
||||
struct mrubypp_method_wrapper {
|
||||
static Ret (T::*method)(MethodArgs...);
|
||||
|
||||
static mrb_value wrapper(mrb_state *mrb, mrb_value self) {
|
||||
auto args = mrubypp_get_args_helper<MethodArgs...>(mrb);
|
||||
T *instance = static_cast<T *>(DATA_PTR(self));
|
||||
if (!instance) {
|
||||
mrb_raise(mrb, E_RUNTIME_ERROR, "Invalid instance");
|
||||
mrb_raise(mrb, E_RUNTIME_ERROR, "invalid instance");
|
||||
}
|
||||
union {
|
||||
Ret (T::*method)(MethodArgs...);
|
||||
void *ptr;
|
||||
} converter;
|
||||
|
||||
converter.ptr = mrb_cptr(mrb_cfunc_env_get(mrb, 0));
|
||||
auto method = converter.method;
|
||||
if constexpr (std::is_same_v<Ret, void>) {
|
||||
std::apply(method, std::tuple_cat(std::make_tuple(instance), args));
|
||||
return mrb_nil_value();
|
||||
@@ -62,14 +67,19 @@ struct mrubypp_method_wrapper {
|
||||
|
||||
template <typename T, typename Ret, typename... MethodArgs>
|
||||
struct mrubypp_const_method_wrapper {
|
||||
static Ret (T::*method)(MethodArgs...) const;
|
||||
|
||||
static mrb_value wrapper(mrb_state *mrb, mrb_value self) {
|
||||
auto args = mrubypp_get_args_helper<MethodArgs...>(mrb);
|
||||
T *instance = static_cast<T *>(DATA_PTR(self));
|
||||
if (!instance) {
|
||||
mrb_raise(mrb, E_RUNTIME_ERROR, "Invalid instance");
|
||||
mrb_raise(mrb, E_RUNTIME_ERROR, "invalid instance");
|
||||
}
|
||||
union {
|
||||
Ret (T::*method)(MethodArgs...) const;
|
||||
void *ptr;
|
||||
} converter;
|
||||
|
||||
converter.ptr = mrb_cptr(mrb_cfunc_env_get(mrb, 0));
|
||||
auto method = converter.method;
|
||||
|
||||
if constexpr (std::is_same_v<Ret, void>) {
|
||||
std::apply(method, std::tuple_cat(std::make_tuple(instance), args));
|
||||
@@ -82,10 +92,16 @@ struct mrubypp_const_method_wrapper {
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Ret, typename... FuncArgs> struct mrubypp_function_wrapper {
|
||||
static Ret (*func)(FuncArgs...);
|
||||
|
||||
template <typename T, typename Ret, typename... FuncArgs>
|
||||
struct mrubypp_function_wrapper {
|
||||
static mrb_value wrapper(mrb_state *mrb, mrb_value self) {
|
||||
union {
|
||||
Ret (*func)(FuncArgs...);
|
||||
void *ptr;
|
||||
} converter;
|
||||
|
||||
converter.ptr = mrb_cptr(mrb_cfunc_env_get(mrb, 0));
|
||||
auto func = converter.func;
|
||||
auto args = mrubypp_get_args_helper<FuncArgs...>(mrb);
|
||||
if constexpr (std::is_same_v<Ret, void>) {
|
||||
std::apply(func, args);
|
||||
@@ -97,34 +113,6 @@ template <typename Ret, typename... FuncArgs> struct mrubypp_function_wrapper {
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename Ret> struct mrubypp_getter_wrapper {
|
||||
static Ret (T::*getter)() const;
|
||||
|
||||
static mrb_value wrapper(mrb_state *mrb, mrb_value self) {
|
||||
T *instance = static_cast<T *>(DATA_PTR(self));
|
||||
if (!instance) {
|
||||
mrb_raise(mrb, E_RUNTIME_ERROR, "Invalid instance");
|
||||
}
|
||||
|
||||
Ret result = (instance->*getter)();
|
||||
return mrubypp_converter<Ret>::to_mrb(mrb, result);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename Ret> struct mrubypp_setter_wrapper {
|
||||
static void (T::*setter)(Ret);
|
||||
|
||||
static mrb_value wrapper(mrb_state *mrb, mrb_value self) {
|
||||
auto args = mrubypp_get_args_helper<Ret>(mrb);
|
||||
T *instance = static_cast<T *>(DATA_PTR(self));
|
||||
if (!instance) {
|
||||
mrb_raise(mrb, E_RUNTIME_ERROR, "Invalid instance");
|
||||
}
|
||||
|
||||
std::apply(setter, std::tuple_cat(std::make_tuple(instance), args));
|
||||
return self;
|
||||
}
|
||||
};
|
||||
template <typename T> class mrubypp_class_builder;
|
||||
|
||||
template <typename T, typename... Args> struct mrubypp_constructor_wrapper {
|
||||
@@ -139,18 +127,6 @@ template <typename T, typename... Args> struct mrubypp_constructor_wrapper {
|
||||
};
|
||||
|
||||
template <typename T> class mrubypp_class_builder {
|
||||
private:
|
||||
mrb_state *mrb_;
|
||||
struct RClass *rclass_;
|
||||
std::string name_;
|
||||
|
||||
static void free_instance(mrb_state *mrb, void *ptr) {
|
||||
if (ptr) {
|
||||
T *instance = static_cast<T *>(ptr);
|
||||
delete instance;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
static const struct mrb_data_type data_type;
|
||||
|
||||
@@ -163,7 +139,7 @@ public:
|
||||
mrb_, rclass_, "initialize",
|
||||
[](mrb_state *mrb, mrb_value self) -> mrb_value {
|
||||
mrb_raise(mrb, E_NOTIMP_ERROR,
|
||||
"Initialize must be defined explicitly");
|
||||
"initialize must be defined explicitly");
|
||||
return self;
|
||||
},
|
||||
MRB_ARGS_ANY());
|
||||
@@ -173,67 +149,120 @@ public:
|
||||
mrb_define_method(mrb_, rclass_, "initialize",
|
||||
&mrubypp_constructor_wrapper<T, Args...>::wrapper,
|
||||
MRB_ARGS_REQ(sizeof...(Args)));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Ret, typename... MethodArgs>
|
||||
mrubypp_class_builder &def_method(const std::string &name,
|
||||
Ret (T::*method)(MethodArgs...)) {
|
||||
mrubypp_method_wrapper<T, Ret, MethodArgs...>::method = method;
|
||||
|
||||
mrb_define_method(mrb_, rclass_, name.c_str(),
|
||||
&mrubypp_method_wrapper<T, Ret, MethodArgs...>::wrapper,
|
||||
MRB_ARGS_REQ(sizeof...(MethodArgs)));
|
||||
mrb_sym method_sym = mrb_intern_cstr(mrb_, name.c_str());
|
||||
union {
|
||||
Ret (T::*method_ptr)(MethodArgs...);
|
||||
void *ptr;
|
||||
} converter;
|
||||
|
||||
converter.method_ptr = method;
|
||||
|
||||
mrb_value env[] = {
|
||||
mrb_cptr_value(mrb_, converter.ptr),
|
||||
};
|
||||
struct RProc *p = mrb_proc_new_cfunc_with_env(
|
||||
mrb_, &mrubypp_method_wrapper<T, Ret, MethodArgs...>::wrapper, 1, env);
|
||||
mrb_method_t m;
|
||||
MRB_METHOD_FROM_PROC(m, p);
|
||||
mrb_define_method_raw(mrb_, rclass_, method_sym, m);
|
||||
// MRB_ARGS_REQ(sizeof...(MethodArgs))
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Ret, typename... MethodArgs>
|
||||
mrubypp_class_builder &def_method(const std::string &name,
|
||||
Ret (T::*method)(MethodArgs...) const) {
|
||||
mrubypp_const_method_wrapper<T, Ret, MethodArgs...>::method = method;
|
||||
|
||||
mrb_define_method(
|
||||
mrb_, rclass_, name.c_str(),
|
||||
&mrubypp_const_method_wrapper<T, Ret, MethodArgs...>::wrapper,
|
||||
MRB_ARGS_REQ(sizeof...(MethodArgs)));
|
||||
mrb_sym method_sym = mrb_intern_cstr(mrb_, name.c_str());
|
||||
union {
|
||||
Ret (T::*method_ptr)(MethodArgs...) const;
|
||||
void *ptr;
|
||||
} converter;
|
||||
|
||||
converter.method_ptr = method;
|
||||
mrb_value env[] = {
|
||||
mrb_cptr_value(mrb_, converter.ptr),
|
||||
};
|
||||
struct RProc *p = mrb_proc_new_cfunc_with_env(
|
||||
mrb_, &mrubypp_const_method_wrapper<T, Ret, MethodArgs...>::wrapper, 1,
|
||||
env);
|
||||
mrb_method_t m;
|
||||
MRB_METHOD_FROM_PROC(m, p);
|
||||
mrb_define_method_raw(mrb_, rclass_, method_sym, m);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Ret, typename... FuncArgs>
|
||||
mrubypp_class_builder &def_class_method(const std::string &name,
|
||||
Ret (*func)(FuncArgs...)) {
|
||||
mrubypp_function_wrapper<Ret, FuncArgs...>::func = func;
|
||||
|
||||
mrb_define_class_method(
|
||||
mrb_, rclass_, name.c_str(),
|
||||
&mrubypp_function_wrapper<Ret, FuncArgs...>::wrapper,
|
||||
MRB_ARGS_REQ(sizeof...(FuncArgs)));
|
||||
union {
|
||||
Ret (*funcPtr)(FuncArgs...);
|
||||
void *ptr;
|
||||
} converter;
|
||||
|
||||
converter.funcPtr = func;
|
||||
mrb_value env[] = {
|
||||
mrb_cptr_value(mrb_, converter.ptr),
|
||||
};
|
||||
|
||||
mrb_sym func_sym = mrb_intern_cstr(mrb_, name.c_str());
|
||||
struct RProc *p = mrb_proc_new_cfunc_with_env(
|
||||
mrb_, &mrubypp_function_wrapper<T, Ret, FuncArgs...>::wrapper, 1, env);
|
||||
mrb_method_t m;
|
||||
MRB_METHOD_FROM_PROC(m, p);
|
||||
|
||||
// register and replace
|
||||
mrb_define_class_method_id(mrb_, rclass_, func_sym, NULL, MRB_ARGS_ANY());
|
||||
mrb_define_method_raw(mrb_, rclass_->c, func_sym, m);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Ret, typename... MethodArgs>
|
||||
// get set
|
||||
template <typename Ret>
|
||||
mrubypp_class_builder &def_property(const std::string &name,
|
||||
Ret (T::*getter)() const,
|
||||
void (T::*setter)(Ret)) {
|
||||
mrubypp_getter_wrapper<T, Ret>::getter = getter;
|
||||
mrb_define_method(mrb_, rclass_, name.c_str(),
|
||||
&mrubypp_getter_wrapper<T, Ret>::wrapper,
|
||||
MRB_ARGS_NONE());
|
||||
|
||||
std::string setter_name = name + "=";
|
||||
mrubypp_setter_wrapper<T, Ret>::setter = setter;
|
||||
mrb_define_method(mrb_, rclass_, setter_name.c_str(),
|
||||
&mrubypp_setter_wrapper<T, Ret>::wrapper,
|
||||
MRB_ARGS_REQ(1));
|
||||
def_method(name, getter);
|
||||
def_method(name + "=", setter);
|
||||
return *this;
|
||||
}
|
||||
|
||||
mrubypp_class_builder &def_native(const std::string &name, mrb_func_t func,
|
||||
mrb_aspec aspec = MRB_ARGS_ANY()) {
|
||||
mrb_define_method(mrb_, rclass_, name.c_str(), func, aspec);
|
||||
return *this;
|
||||
}
|
||||
|
||||
[[nodiscard]] struct RClass *get_rclass() const { return rclass_; }
|
||||
|
||||
[[nodiscard]] static T *get_this(mrb_state *mrb, mrb_value value) {
|
||||
T *instance = static_cast<T *>(DATA_PTR(value));
|
||||
if (!instance) {
|
||||
mrb_raise(mrb, E_RUNTIME_ERROR, "invalid instance");
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private:
|
||||
static void free_instance(mrb_state *mrb, void *ptr) {
|
||||
if (ptr) {
|
||||
T *instance = static_cast<T *>(ptr);
|
||||
delete instance;
|
||||
}
|
||||
}
|
||||
static std::map<std::string, mrb_method_t> method_map;
|
||||
|
||||
mrb_state *mrb_;
|
||||
struct RClass *rclass_;
|
||||
std::string name_;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
@@ -241,20 +270,4 @@ const struct mrb_data_type mrubypp_class_builder<T>::data_type = {
|
||||
typeid(T).name(), mrubypp_class_builder<T>::free_instance
|
||||
};
|
||||
|
||||
template <typename T, typename Ret, typename... MethodArgs>
|
||||
Ret (T::*mrubypp_method_wrapper<T, Ret, MethodArgs...>::method)(MethodArgs...);
|
||||
|
||||
template <typename T, typename Ret, typename... MethodArgs>
|
||||
Ret (T::*mrubypp_const_method_wrapper<T, Ret, MethodArgs...>::method)(
|
||||
MethodArgs...) const;
|
||||
|
||||
template <typename Ret, typename... FuncArgs>
|
||||
Ret (*mrubypp_function_wrapper<Ret, FuncArgs...>::func)(FuncArgs...);
|
||||
|
||||
template <typename T, typename Ret>
|
||||
Ret (T::*mrubypp_getter_wrapper<T, Ret>::getter)() const;
|
||||
|
||||
template <typename T, typename Ret>
|
||||
void (T::*mrubypp_setter_wrapper<T, Ret>::setter)(Ret);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user