fix method bind
This commit is contained in:
32
mrubypp.h
32
mrubypp.h
@@ -11,42 +11,42 @@
|
|||||||
|
|
||||||
#include <mruby/compile.h>
|
#include <mruby/compile.h>
|
||||||
|
|
||||||
// 支持自定义类型注册
|
|
||||||
class mrubypp {
|
class mrubypp {
|
||||||
public:
|
public:
|
||||||
mrubypp() { mrb = mrb_open(); }
|
mrubypp() { mrb_ = mrb_open(); }
|
||||||
~mrubypp() { mrb_close(mrb); }
|
~mrubypp() { mrb_close(mrb_); }
|
||||||
void load(const std::string &str) {
|
void load(const std::string &str) {
|
||||||
if (!mrb)
|
if (!mrb_)
|
||||||
return;
|
return;
|
||||||
mrb_load_string(mrb, str.c_str());
|
mrb_load_string(mrb_, str.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T> T call(const std::string &funcName) {
|
template <typename T> T call(const std::string &funcName) {
|
||||||
mrubypp_arena_guard guard(mrb);
|
mrubypp_arena_guard guard(mrb_);
|
||||||
mrb_value result = mrb_funcall(mrb, mrb_top_self(mrb), funcName.data(), 0);
|
mrb_value result =
|
||||||
return mrubypp_converter<T>::from_mrb(mrb, result);
|
mrb_funcall(mrb_, mrb_top_self(mrb_), funcName.data(), 0);
|
||||||
|
return mrubypp_converter<T>::from_mrb(mrb_, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename... Args>
|
template <typename T, typename... Args>
|
||||||
T call(const std::string &funcName, Args... args) {
|
T call(const std::string &funcName, Args... args) {
|
||||||
mrubypp_arena_guard guard(mrb);
|
mrubypp_arena_guard guard(mrb_);
|
||||||
mrb_value argv[] = {mrubypp_converter<Args>::to_mrb(mrb, args)...};
|
mrb_value argv[] = {mrubypp_converter<Args>::to_mrb(mrb_, args)...};
|
||||||
mrb_sym sym = mrb_intern_cstr(mrb, funcName.data());
|
mrb_sym sym = mrb_intern_cstr(mrb_, funcName.data());
|
||||||
mrb_value result =
|
mrb_value result =
|
||||||
mrb_funcall_argv(mrb, mrb_top_self(mrb), sym, sizeof...(Args), argv);
|
mrb_funcall_argv(mrb_, mrb_top_self(mrb_), sym, sizeof...(Args), argv);
|
||||||
return mrubypp_converter<T>::from_mrb(mrb, result);
|
return mrubypp_converter<T>::from_mrb(mrb_, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
mrubypp_class_builder<T> class_builder(const std::string &class_name) {
|
mrubypp_class_builder<T> class_builder(const std::string &class_name) {
|
||||||
return mrubypp_class_builder<T>(mrb, class_name);
|
return mrubypp_class_builder<T>(mrb_, class_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] mrb_state *get_mrb() const { return mrb; }
|
[[nodiscard]] mrb_state *get_mrb() const { return mrb_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mrb_state *mrb;
|
mrb_state *mrb_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MRUBYPP_H
|
#endif // MRUBYPP_H
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include <mruby.h>
|
#include <mruby.h>
|
||||||
|
|
||||||
|
// gc arena
|
||||||
class mrubypp_arena_guard {
|
class mrubypp_arena_guard {
|
||||||
public:
|
public:
|
||||||
explicit mrubypp_arena_guard(mrb_state *mrb) : mrb(mrb) {
|
explicit mrubypp_arena_guard(mrb_state *mrb) : mrb(mrb) {
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#include <mruby/class.h>
|
#include <mruby/class.h>
|
||||||
#include <mruby/data.h>
|
#include <mruby/data.h>
|
||||||
|
#include <mruby/proc.h>
|
||||||
|
|
||||||
template <typename... Args, size_t... Is>
|
template <typename... Args, size_t... Is>
|
||||||
std::tuple<Args...> mrubypp_get_args_helper_impl(mrb_state *mrb,
|
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>
|
template <typename T, typename Ret, typename... MethodArgs>
|
||||||
struct mrubypp_method_wrapper {
|
struct mrubypp_method_wrapper {
|
||||||
static Ret (T::*method)(MethodArgs...);
|
|
||||||
|
|
||||||
static mrb_value wrapper(mrb_state *mrb, mrb_value self) {
|
static mrb_value wrapper(mrb_state *mrb, mrb_value self) {
|
||||||
auto args = mrubypp_get_args_helper<MethodArgs...>(mrb);
|
auto args = mrubypp_get_args_helper<MethodArgs...>(mrb);
|
||||||
T *instance = static_cast<T *>(DATA_PTR(self));
|
T *instance = static_cast<T *>(DATA_PTR(self));
|
||||||
if (!instance) {
|
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>) {
|
if constexpr (std::is_same_v<Ret, void>) {
|
||||||
std::apply(method, std::tuple_cat(std::make_tuple(instance), args));
|
std::apply(method, std::tuple_cat(std::make_tuple(instance), args));
|
||||||
return mrb_nil_value();
|
return mrb_nil_value();
|
||||||
@@ -62,14 +67,19 @@ struct mrubypp_method_wrapper {
|
|||||||
|
|
||||||
template <typename T, typename Ret, typename... MethodArgs>
|
template <typename T, typename Ret, typename... MethodArgs>
|
||||||
struct mrubypp_const_method_wrapper {
|
struct mrubypp_const_method_wrapper {
|
||||||
static Ret (T::*method)(MethodArgs...) const;
|
|
||||||
|
|
||||||
static mrb_value wrapper(mrb_state *mrb, mrb_value self) {
|
static mrb_value wrapper(mrb_state *mrb, mrb_value self) {
|
||||||
auto args = mrubypp_get_args_helper<MethodArgs...>(mrb);
|
auto args = mrubypp_get_args_helper<MethodArgs...>(mrb);
|
||||||
T *instance = static_cast<T *>(DATA_PTR(self));
|
T *instance = static_cast<T *>(DATA_PTR(self));
|
||||||
if (!instance) {
|
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>) {
|
if constexpr (std::is_same_v<Ret, void>) {
|
||||||
std::apply(method, std::tuple_cat(std::make_tuple(instance), args));
|
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 {
|
template <typename T, typename Ret, typename... FuncArgs>
|
||||||
static Ret (*func)(FuncArgs...);
|
struct mrubypp_function_wrapper {
|
||||||
|
|
||||||
static mrb_value wrapper(mrb_state *mrb, mrb_value self) {
|
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);
|
auto args = mrubypp_get_args_helper<FuncArgs...>(mrb);
|
||||||
if constexpr (std::is_same_v<Ret, void>) {
|
if constexpr (std::is_same_v<Ret, void>) {
|
||||||
std::apply(func, args);
|
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> class mrubypp_class_builder;
|
||||||
|
|
||||||
template <typename T, typename... Args> struct mrubypp_constructor_wrapper {
|
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 {
|
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:
|
public:
|
||||||
static const struct mrb_data_type data_type;
|
static const struct mrb_data_type data_type;
|
||||||
|
|
||||||
@@ -163,7 +139,7 @@ public:
|
|||||||
mrb_, rclass_, "initialize",
|
mrb_, rclass_, "initialize",
|
||||||
[](mrb_state *mrb, mrb_value self) -> mrb_value {
|
[](mrb_state *mrb, mrb_value self) -> mrb_value {
|
||||||
mrb_raise(mrb, E_NOTIMP_ERROR,
|
mrb_raise(mrb, E_NOTIMP_ERROR,
|
||||||
"Initialize must be defined explicitly");
|
"initialize must be defined explicitly");
|
||||||
return self;
|
return self;
|
||||||
},
|
},
|
||||||
MRB_ARGS_ANY());
|
MRB_ARGS_ANY());
|
||||||
@@ -173,67 +149,120 @@ public:
|
|||||||
mrb_define_method(mrb_, rclass_, "initialize",
|
mrb_define_method(mrb_, rclass_, "initialize",
|
||||||
&mrubypp_constructor_wrapper<T, Args...>::wrapper,
|
&mrubypp_constructor_wrapper<T, Args...>::wrapper,
|
||||||
MRB_ARGS_REQ(sizeof...(Args)));
|
MRB_ARGS_REQ(sizeof...(Args)));
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Ret, typename... MethodArgs>
|
template <typename Ret, typename... MethodArgs>
|
||||||
mrubypp_class_builder &def_method(const std::string &name,
|
mrubypp_class_builder &def_method(const std::string &name,
|
||||||
Ret (T::*method)(MethodArgs...)) {
|
Ret (T::*method)(MethodArgs...)) {
|
||||||
mrubypp_method_wrapper<T, Ret, MethodArgs...>::method = method;
|
|
||||||
|
|
||||||
mrb_define_method(mrb_, rclass_, name.c_str(),
|
mrb_sym method_sym = mrb_intern_cstr(mrb_, name.c_str());
|
||||||
&mrubypp_method_wrapper<T, Ret, MethodArgs...>::wrapper,
|
union {
|
||||||
MRB_ARGS_REQ(sizeof...(MethodArgs)));
|
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;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Ret, typename... MethodArgs>
|
template <typename Ret, typename... MethodArgs>
|
||||||
mrubypp_class_builder &def_method(const std::string &name,
|
mrubypp_class_builder &def_method(const std::string &name,
|
||||||
Ret (T::*method)(MethodArgs...) const) {
|
Ret (T::*method)(MethodArgs...) const) {
|
||||||
mrubypp_const_method_wrapper<T, Ret, MethodArgs...>::method = method;
|
mrb_sym method_sym = mrb_intern_cstr(mrb_, name.c_str());
|
||||||
|
union {
|
||||||
mrb_define_method(
|
Ret (T::*method_ptr)(MethodArgs...) const;
|
||||||
mrb_, rclass_, name.c_str(),
|
void *ptr;
|
||||||
&mrubypp_const_method_wrapper<T, Ret, MethodArgs...>::wrapper,
|
} converter;
|
||||||
MRB_ARGS_REQ(sizeof...(MethodArgs)));
|
|
||||||
|
|
||||||
|
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;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Ret, typename... FuncArgs>
|
template <typename Ret, typename... FuncArgs>
|
||||||
mrubypp_class_builder &def_class_method(const std::string &name,
|
mrubypp_class_builder &def_class_method(const std::string &name,
|
||||||
Ret (*func)(FuncArgs...)) {
|
Ret (*func)(FuncArgs...)) {
|
||||||
mrubypp_function_wrapper<Ret, FuncArgs...>::func = func;
|
|
||||||
|
|
||||||
mrb_define_class_method(
|
union {
|
||||||
mrb_, rclass_, name.c_str(),
|
Ret (*funcPtr)(FuncArgs...);
|
||||||
&mrubypp_function_wrapper<Ret, FuncArgs...>::wrapper,
|
void *ptr;
|
||||||
MRB_ARGS_REQ(sizeof...(FuncArgs)));
|
} 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;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Ret, typename... MethodArgs>
|
// get set
|
||||||
|
template <typename Ret>
|
||||||
mrubypp_class_builder &def_property(const std::string &name,
|
mrubypp_class_builder &def_property(const std::string &name,
|
||||||
Ret (T::*getter)() const,
|
Ret (T::*getter)() const,
|
||||||
void (T::*setter)(Ret)) {
|
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 + "=";
|
def_method(name, getter);
|
||||||
mrubypp_setter_wrapper<T, Ret>::setter = setter;
|
def_method(name + "=", setter);
|
||||||
mrb_define_method(mrb_, rclass_, setter_name.c_str(),
|
return *this;
|
||||||
&mrubypp_setter_wrapper<T, Ret>::wrapper,
|
}
|
||||||
MRB_ARGS_REQ(1));
|
|
||||||
|
|
||||||
|
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;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] struct RClass *get_rclass() const { return rclass_; }
|
[[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>
|
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
|
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
|
#endif
|
||||||
|
|||||||
@@ -29,6 +29,15 @@ template <> struct mrubypp_converter<int> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <> struct mrubypp_converter<unsigned int> {
|
||||||
|
static mrb_value to_mrb(mrb_state *mrb, unsigned int var) {
|
||||||
|
return mrb_fixnum_value(var);
|
||||||
|
}
|
||||||
|
static int from_mrb(mrb_state *mrb, mrb_value value) {
|
||||||
|
return mrb_fixnum(value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template <> struct mrubypp_converter<float> {
|
template <> struct mrubypp_converter<float> {
|
||||||
static mrb_value to_mrb(mrb_state *mrb, float var) {
|
static mrb_value to_mrb(mrb_state *mrb, float var) {
|
||||||
return mrb_float_value(mrb, var);
|
return mrb_float_value(mrb, var);
|
||||||
@@ -60,6 +69,12 @@ template <> struct mrubypp_converter<std::string> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <> struct mrubypp_converter<const char *> {
|
||||||
|
static mrb_value to_mrb(mrb_state *mrb, const char *var) {
|
||||||
|
return mrb_str_new(mrb, var, (mrb_int)strlen(var));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template <typename T> struct mrubypp_converter<std::vector<T>> {
|
template <typename T> struct mrubypp_converter<std::vector<T>> {
|
||||||
static mrb_value to_mrb(mrb_state *mrb, const std::vector<T> &var) {
|
static mrb_value to_mrb(mrb_state *mrb, const std::vector<T> &var) {
|
||||||
mrb_value ary = mrb_ary_new_capa(mrb, static_cast<mrb_int>(var.size()));
|
mrb_value ary = mrb_ary_new_capa(mrb, static_cast<mrb_int>(var.size()));
|
||||||
|
|||||||
@@ -16,15 +16,22 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
int get_x() const { return x_; }
|
int get_x() const { return x_; }
|
||||||
void set_x(int x) { x_ = x; }
|
void set_x(int x) {
|
||||||
|
//
|
||||||
|
x_ = x;
|
||||||
|
}
|
||||||
|
|
||||||
int get_y() const { return y_; }
|
int get_y() const { return y_; }
|
||||||
void set_y(int y) { y_ = y; }
|
void set_y(int y) {
|
||||||
|
//
|
||||||
|
y_ = y;
|
||||||
|
}
|
||||||
|
|
||||||
void add(const Point &other) {
|
void add(const Point &other) {
|
||||||
this->x_ += other.x_;
|
this->x_ += other.x_;
|
||||||
this->y_ += other.y_;
|
this->y_ += other.y_;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int none() { return 1; }
|
static int none() { return 1; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -32,6 +39,14 @@ private:
|
|||||||
int y_;
|
int y_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static mrb_value point_native_div(mrb_state *mrb, mrb_value self) {
|
||||||
|
auto point = mrubypp_class_builder<Point>::get_this(mrb, self);
|
||||||
|
auto divisor = mrubypp_converter<int>::from_mrb(mrb, mrb_get_arg1(mrb));
|
||||||
|
point->set_x(point->get_x() / divisor);
|
||||||
|
point->set_y(point->get_y() / divisor);
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
template <> struct mrubypp_converter<Point> {
|
template <> struct mrubypp_converter<Point> {
|
||||||
static mrb_value to_mrb(mrb_state *mrb, const Point &var) {
|
static mrb_value to_mrb(mrb_state *mrb, const Point &var) {
|
||||||
mrb_value obj = mrb_obj_value(
|
mrb_value obj = mrb_obj_value(
|
||||||
@@ -55,20 +70,51 @@ TEST_CASE("Point", "[class]") {
|
|||||||
.def_constructor<int, int>()
|
.def_constructor<int, int>()
|
||||||
.def_method("add", &Point::add)
|
.def_method("add", &Point::add)
|
||||||
.def_class_method("none", &Point::none)
|
.def_class_method("none", &Point::none)
|
||||||
.def_property("x", &Point::get_x, &Point::set_x);
|
.def_property("x", &Point::get_x, &Point::set_x)
|
||||||
|
.def_property("y", &Point::get_y, &Point::set_y)
|
||||||
|
.def_native("div", point_native_div, MRB_ARGS_REQ(1));
|
||||||
|
|
||||||
engine.load(R"(
|
engine.load(R"(
|
||||||
def test_point()
|
def test_method()
|
||||||
|
p = Point.new(3, 4)
|
||||||
|
p.add(p)
|
||||||
|
return p
|
||||||
|
end
|
||||||
|
def test_property()
|
||||||
p = Point.new(3, 4)
|
p = Point.new(3, 4)
|
||||||
p.x = 10
|
p.x = 10
|
||||||
p.add(p)
|
p.y = p.y + p.y
|
||||||
p.x += Point::none()
|
|
||||||
return p
|
return p
|
||||||
end
|
end
|
||||||
|
def test_native()
|
||||||
|
p = Point.new(4, 8)
|
||||||
|
p.div(2)
|
||||||
|
return p
|
||||||
|
end
|
||||||
|
def test_class_method()
|
||||||
|
return Point::none()
|
||||||
|
end
|
||||||
)");
|
)");
|
||||||
|
|
||||||
auto point_result = engine.call<Point>("test_point");
|
SECTION("test_method") {
|
||||||
|
auto point_result = engine.call<Point>("test_method");
|
||||||
REQUIRE(point_result.get_x() == 21);
|
REQUIRE(point_result.get_x() == 6);
|
||||||
REQUIRE(point_result.get_y() == 8);
|
REQUIRE(point_result.get_y() == 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("test_property") {
|
||||||
|
auto point_result = engine.call<Point>("test_property");
|
||||||
|
REQUIRE(point_result.get_x() == 10);
|
||||||
|
REQUIRE(point_result.get_y() == 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("test_native") {
|
||||||
|
auto point_result = engine.call<Point>("test_native");
|
||||||
|
REQUIRE(point_result.get_x() == 2);
|
||||||
|
REQUIRE(point_result.get_y() == 4);
|
||||||
|
}
|
||||||
|
SECTION("test_class_method") {
|
||||||
|
auto result = engine.call<int>("test_class_method");
|
||||||
|
REQUIRE(result == 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user