fix failed bind method in gcc/clang
All checks were successful
ubuntu / Explore-Gitea-Actions (push) Successful in 1m39s
All checks were successful
ubuntu / Explore-Gitea-Actions (push) Successful in 1m39s
This commit is contained in:
@@ -4,6 +4,7 @@ project(mrubypp LANGUAGES CXX)
|
|||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
set(mruby_ROOT "/mnt/d/Sources/mruby/build/host")
|
||||||
|
|
||||||
option(MRUBYPP_BUILD_TEST "Build Catch2 Test" OFF)
|
option(MRUBYPP_BUILD_TEST "Build Catch2 Test" OFF)
|
||||||
|
|
||||||
|
|||||||
@@ -41,19 +41,32 @@ 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 {
|
||||||
|
using MethodType = Ret (T::*)(MethodArgs...);
|
||||||
|
|
||||||
|
// TODO, fix memory leak
|
||||||
|
static void *method_to_ptr(MethodType method) {
|
||||||
|
auto ptr = malloc(sizeof(MethodType));
|
||||||
|
memcpy(ptr, &method, sizeof(MethodType));
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static MethodType ptr_to_method(void *ptr) {
|
||||||
|
MethodType method;
|
||||||
|
memcpy(&method, ptr, sizeof(MethodType));
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
void *method_ptr = mrb_cptr(mrb_cfunc_env_get(mrb, 0));
|
||||||
|
auto method = ptr_to_method(method_ptr);
|
||||||
|
|
||||||
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();
|
||||||
@@ -67,23 +80,34 @@ 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 {
|
||||||
|
using MethodType = Ret (T::*)(MethodArgs...) const;
|
||||||
|
|
||||||
|
// TODO, fix memory leak
|
||||||
|
static void *method_to_ptr(MethodType method) {
|
||||||
|
auto ptr = malloc(sizeof(MethodType));
|
||||||
|
memcpy(ptr, &method, sizeof(MethodType));
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static MethodType ptr_to_method(void *ptr) {
|
||||||
|
MethodType method;
|
||||||
|
memcpy(&method, ptr, sizeof(MethodType));
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
|
void *method_ptr = mrb_cptr(mrb_cfunc_env_get(mrb, 0));
|
||||||
|
auto method = ptr_to_method(method_ptr);
|
||||||
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();
|
|
||||||
} else {
|
} else {
|
||||||
Ret result =
|
Ret result =
|
||||||
std::apply(method, std::tuple_cat(std::make_tuple(instance), args));
|
std::apply(method, std::tuple_cat(std::make_tuple(instance), args));
|
||||||
@@ -94,14 +118,10 @@ struct mrubypp_const_method_wrapper {
|
|||||||
|
|
||||||
template<typename T, typename Ret, typename... FuncArgs>
|
template<typename T, typename Ret, typename... FuncArgs>
|
||||||
struct mrubypp_function_wrapper {
|
struct mrubypp_function_wrapper {
|
||||||
static mrb_value wrapper(mrb_state *mrb, mrb_value self) {
|
using FunctionType = Ret (*)(FuncArgs...);
|
||||||
union {
|
|
||||||
Ret (*func)(FuncArgs...);
|
|
||||||
void *ptr;
|
|
||||||
} converter;
|
|
||||||
|
|
||||||
converter.ptr = mrb_cptr(mrb_cfunc_env_get(mrb, 0));
|
static mrb_value wrapper(mrb_state *mrb, mrb_value self) {
|
||||||
auto func = converter.func;
|
auto func = (FunctionType) mrb_cptr(mrb_cfunc_env_get(mrb, 0));
|
||||||
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);
|
||||||
@@ -113,9 +133,11 @@ struct mrubypp_function_wrapper {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
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 {
|
||||||
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<Args...>(mrb);
|
auto args = mrubypp_get_args_helper<Args...>(mrb);
|
||||||
T *instance = std::apply([](Args... args) { return new T(args...); }, args);
|
T *instance = std::apply([](Args... args) { return new T(args...); }, args);
|
||||||
@@ -126,7 +148,8 @@ template <typename T, typename... Args> struct mrubypp_constructor_wrapper {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T> class mrubypp_class_builder {
|
template<typename T>
|
||||||
|
class mrubypp_class_builder {
|
||||||
public:
|
public:
|
||||||
static const struct mrb_data_type data_type;
|
static const struct mrb_data_type data_type;
|
||||||
|
|
||||||
@@ -145,7 +168,8 @@ public:
|
|||||||
MRB_ARGS_ANY());
|
MRB_ARGS_ANY());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args> mrubypp_class_builder &def_constructor() {
|
template<typename... Args>
|
||||||
|
mrubypp_class_builder &def_constructor() {
|
||||||
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)));
|
||||||
@@ -155,20 +179,16 @@ public:
|
|||||||
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...)) {
|
||||||
|
|
||||||
mrb_sym method_sym = mrb_intern_cstr(mrb_, name.c_str());
|
mrb_sym method_sym = mrb_intern_cstr(mrb_, name.c_str());
|
||||||
union {
|
|
||||||
Ret (T::*method_ptr)(MethodArgs...);
|
|
||||||
void *ptr;
|
|
||||||
} converter;
|
|
||||||
|
|
||||||
converter.method_ptr = method;
|
using wrap = mrubypp_method_wrapper<T, Ret, MethodArgs...>;
|
||||||
|
auto ptr = wrap::method_to_ptr(method);
|
||||||
|
|
||||||
mrb_value env[] = {
|
mrb_value env[] = {
|
||||||
mrb_cptr_value(mrb_, converter.ptr),
|
mrb_cptr_value(mrb_, ptr),
|
||||||
};
|
};
|
||||||
struct RProc *p = mrb_proc_new_cfunc_with_env(
|
struct RProc *p = mrb_proc_new_cfunc_with_env(
|
||||||
mrb_, &mrubypp_method_wrapper<T, Ret, MethodArgs...>::wrapper, 1, env);
|
mrb_, &wrap::wrapper, 1, env);
|
||||||
mrb_method_t m;
|
mrb_method_t m;
|
||||||
MRB_METHOD_FROM_PROC(m, p);
|
MRB_METHOD_FROM_PROC(m, p);
|
||||||
mrb_define_method_raw(mrb_, rclass_, method_sym, m);
|
mrb_define_method_raw(mrb_, rclass_, method_sym, m);
|
||||||
@@ -180,17 +200,17 @@ public:
|
|||||||
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) {
|
||||||
mrb_sym method_sym = mrb_intern_cstr(mrb_, name.c_str());
|
mrb_sym method_sym = mrb_intern_cstr(mrb_, name.c_str());
|
||||||
union {
|
using wrap = mrubypp_const_method_wrapper<T, Ret, MethodArgs...>;
|
||||||
Ret (T::*method_ptr)(MethodArgs...) const;
|
|
||||||
void *ptr;
|
|
||||||
} converter;
|
|
||||||
|
|
||||||
converter.method_ptr = method;
|
auto ptr = wrap::method_to_ptr(method);
|
||||||
|
auto obj = mrb_cptr_value(mrb_, ptr);
|
||||||
|
mrb_gc_protect(mrb_, obj);
|
||||||
mrb_value env[] = {
|
mrb_value env[] = {
|
||||||
mrb_cptr_value(mrb_, converter.ptr),
|
obj
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RProc *p = mrb_proc_new_cfunc_with_env(
|
struct RProc *p = mrb_proc_new_cfunc_with_env(
|
||||||
mrb_, &mrubypp_const_method_wrapper<T, Ret, MethodArgs...>::wrapper, 1,
|
mrb_, &wrap::wrapper, 1,
|
||||||
env);
|
env);
|
||||||
mrb_method_t m;
|
mrb_method_t m;
|
||||||
MRB_METHOD_FROM_PROC(m, p);
|
MRB_METHOD_FROM_PROC(m, p);
|
||||||
@@ -201,20 +221,14 @@ public:
|
|||||||
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...)) {
|
||||||
|
using wrap = mrubypp_function_wrapper<T, Ret, FuncArgs...>;
|
||||||
union {
|
|
||||||
Ret (*funcPtr)(FuncArgs...);
|
|
||||||
void *ptr;
|
|
||||||
} converter;
|
|
||||||
|
|
||||||
converter.funcPtr = func;
|
|
||||||
mrb_value env[] = {
|
mrb_value env[] = {
|
||||||
mrb_cptr_value(mrb_, converter.ptr),
|
mrb_cptr_value(mrb_, (void *) func),
|
||||||
};
|
};
|
||||||
|
|
||||||
mrb_sym func_sym = mrb_intern_cstr(mrb_, name.c_str());
|
mrb_sym func_sym = mrb_intern_cstr(mrb_, name.c_str());
|
||||||
struct RProc *p = mrb_proc_new_cfunc_with_env(
|
struct RProc *p = mrb_proc_new_cfunc_with_env(
|
||||||
mrb_, &mrubypp_function_wrapper<T, Ret, FuncArgs...>::wrapper, 1, env);
|
mrb_, &wrap::wrapper, 1, env);
|
||||||
mrb_method_t m;
|
mrb_method_t m;
|
||||||
MRB_METHOD_FROM_PROC(m, p);
|
MRB_METHOD_FROM_PROC(m, p);
|
||||||
|
|
||||||
@@ -229,7 +243,6 @@ public:
|
|||||||
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)) {
|
||||||
|
|
||||||
def_method(name, getter);
|
def_method(name, getter);
|
||||||
def_method(name + "=", setter);
|
def_method(name + "=", setter);
|
||||||
return *this;
|
return *this;
|
||||||
@@ -258,7 +271,7 @@ private:
|
|||||||
delete instance;
|
delete instance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static std::map<std::string, mrb_method_t> method_map;
|
|
||||||
|
|
||||||
mrb_state *mrb_;
|
mrb_state *mrb_;
|
||||||
struct RClass *rclass_;
|
struct RClass *rclass_;
|
||||||
|
|||||||
@@ -8,7 +8,8 @@
|
|||||||
|
|
||||||
class Point {
|
class Point {
|
||||||
public:
|
public:
|
||||||
Point(int x, int y) : x_(x), y_(y) {}
|
Point(int x, int y) : x_(x), y_(y) {
|
||||||
|
}
|
||||||
|
|
||||||
void set_values(int x, int y) {
|
void set_values(int x, int y) {
|
||||||
x_ = x;
|
x_ = x;
|
||||||
@@ -16,10 +17,16 @@ 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_;
|
||||||
@@ -41,7 +48,8 @@ static mrb_value point_native_div(mrb_state *mrb, mrb_value self) {
|
|||||||
return self;
|
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(
|
||||||
mrb_data_object_alloc(mrb, mrb->object_class, new Point(var),
|
mrb_data_object_alloc(mrb, mrb->object_class, new Point(var),
|
||||||
|
|||||||
Reference in New Issue
Block a user