Compare commits
3 Commits
e38f5850d3
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 45bf416230 | |||
| e67f4c3a4d | |||
| ef4ada6035 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,4 +1,5 @@
|
|||||||
cmake-*/
|
cmake-*/
|
||||||
build/
|
build/
|
||||||
.idea/
|
.idea/
|
||||||
|
CMakeSettings.json
|
||||||
|
.vs/
|
||||||
|
|||||||
@@ -37,11 +37,11 @@ template <typename T, typename Ret, typename... MethodArgs>
|
|||||||
struct method_wrapper {
|
struct method_wrapper {
|
||||||
using MethodType = Ret (T::*)(MethodArgs...);
|
using MethodType = Ret (T::*)(MethodArgs...);
|
||||||
|
|
||||||
// TODO, fix memory leak
|
static mrb_value method_to_ptr(mrb_state* mrb, MethodType method) {
|
||||||
static void *method_to_ptr(MethodType method) {
|
mrb_value bytes = mrb_str_new(mrb, NULL, sizeof(MethodType));
|
||||||
auto ptr = malloc(sizeof(MethodType));
|
void* ptr = (void*)RSTRING_PTR(bytes);
|
||||||
memcpy(ptr, &method, sizeof(MethodType));
|
memcpy(ptr, &method, sizeof(MethodType));
|
||||||
return ptr;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
static MethodType ptr_to_method(void *ptr) {
|
static MethodType ptr_to_method(void *ptr) {
|
||||||
@@ -57,7 +57,7 @@ struct method_wrapper {
|
|||||||
mrb_raise(mrb, E_RUNTIME_ERROR, "invalid instance");
|
mrb_raise(mrb, E_RUNTIME_ERROR, "invalid instance");
|
||||||
}
|
}
|
||||||
|
|
||||||
void *method_ptr = mrb_cptr(mrb_cfunc_env_get(mrb, 0));
|
void *method_ptr = (void*)RSTRING_PTR(mrb_cfunc_env_get(mrb, 0));
|
||||||
auto method = ptr_to_method(method_ptr);
|
auto method = ptr_to_method(method_ptr);
|
||||||
|
|
||||||
if constexpr (std::is_same_v<Ret, void>) {
|
if constexpr (std::is_same_v<Ret, void>) {
|
||||||
@@ -75,11 +75,11 @@ template <typename T, typename Ret, typename... MethodArgs>
|
|||||||
struct const_method_wrapper {
|
struct const_method_wrapper {
|
||||||
using MethodType = Ret (T::*)(MethodArgs...) const;
|
using MethodType = Ret (T::*)(MethodArgs...) const;
|
||||||
|
|
||||||
// TODO, fix memory leak
|
static mrb_value method_to_ptr(mrb_state* mrb, MethodType method) {
|
||||||
static void *method_to_ptr(MethodType method) {
|
mrb_value bytes = mrb_str_new(mrb, NULL, sizeof(MethodType));
|
||||||
auto ptr = malloc(sizeof(MethodType));
|
void* ptr = (void*)RSTRING_PTR(bytes);
|
||||||
memcpy(ptr, &method, sizeof(MethodType));
|
memcpy(ptr, &method, sizeof(MethodType));
|
||||||
return ptr;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
static MethodType ptr_to_method(void *ptr) {
|
static MethodType ptr_to_method(void *ptr) {
|
||||||
@@ -95,7 +95,7 @@ struct const_method_wrapper {
|
|||||||
mrb_raise(mrb, E_RUNTIME_ERROR, "invalid instance");
|
mrb_raise(mrb, E_RUNTIME_ERROR, "invalid instance");
|
||||||
}
|
}
|
||||||
|
|
||||||
void *method_ptr = mrb_cptr(mrb_cfunc_env_get(mrb, 0));
|
void *method_ptr = (void*)RSTRING_PTR(mrb_cfunc_env_get(mrb, 0));
|
||||||
auto method = ptr_to_method(method_ptr);
|
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));
|
||||||
@@ -164,17 +164,20 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bind_class& def_constructor(mrb_func_t func,
|
||||||
|
mrb_aspec aspec = MRB_ARGS_ANY()) {
|
||||||
|
return def_native("initialize", func, aspec);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename Ret, typename... MethodArgs>
|
template <typename Ret, typename... MethodArgs>
|
||||||
bind_class &def_method(const std::string &name,
|
bind_class &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());
|
||||||
|
|
||||||
using wrap = method_wrapper<T, Ret, MethodArgs...>;
|
using wrap = method_wrapper<T, Ret, MethodArgs...>;
|
||||||
auto ptr = wrap::method_to_ptr(method);
|
auto obj = wrap::method_to_ptr(mrb_, method);
|
||||||
|
mrb_gc_protect(mrb_, obj);
|
||||||
mrb_value env[] = {
|
mrb_value env[] = { obj };
|
||||||
mrb_cptr_value(mrb_, ptr),
|
|
||||||
};
|
|
||||||
struct RProc *p = mrb_proc_new_cfunc_with_env(mrb_, &wrap::wrapper, 1, env);
|
struct RProc *p = mrb_proc_new_cfunc_with_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);
|
||||||
@@ -189,10 +192,10 @@ public:
|
|||||||
mrb_sym method_sym = mrb_intern_cstr(mrb_, name.c_str());
|
mrb_sym method_sym = mrb_intern_cstr(mrb_, name.c_str());
|
||||||
using wrap = const_method_wrapper<T, Ret, MethodArgs...>;
|
using wrap = const_method_wrapper<T, Ret, MethodArgs...>;
|
||||||
|
|
||||||
auto ptr = wrap::method_to_ptr(method);
|
auto obj = wrap::method_to_ptr(mrb_, method);
|
||||||
auto obj = mrb_cptr_value(mrb_, ptr);
|
|
||||||
mrb_gc_protect(mrb_, obj);
|
mrb_gc_protect(mrb_, obj);
|
||||||
mrb_value env[] = {obj};
|
mrb_value env[] = { obj };
|
||||||
|
|
||||||
struct RProc *p = mrb_proc_new_cfunc_with_env(mrb_, &wrap::wrapper, 1, env);
|
struct RProc *p = mrb_proc_new_cfunc_with_env(mrb_, &wrap::wrapper, 1, env);
|
||||||
mrb_method_t m;
|
mrb_method_t m;
|
||||||
|
|||||||
@@ -36,6 +36,27 @@ private:
|
|||||||
int y_;
|
int y_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static mrb_value point_native_init(mrb_state* mrb, mrb_value self) {
|
||||||
|
auto count = mrb_get_argc(mrb);
|
||||||
|
Point* p = nullptr;
|
||||||
|
if (count == 0)
|
||||||
|
{
|
||||||
|
p = new Point(0, 0);
|
||||||
|
} else if (count == 1) {
|
||||||
|
auto argv = mrb_get_argv(mrb);
|
||||||
|
p = new Point(mrb_as_float(mrb, argv[0]), 0);
|
||||||
|
} else if (count == 2) {
|
||||||
|
auto argv = mrb_get_argv(mrb);
|
||||||
|
p = new Point(mrb_as_float(mrb, argv[0]), mrb_as_float(mrb, argv[1]));
|
||||||
|
} else {
|
||||||
|
mrb_raise(mrb, E_ARGUMENT_ERROR, "Point wrong number of arguments");
|
||||||
|
}
|
||||||
|
|
||||||
|
DATA_PTR(self) = p;
|
||||||
|
DATA_TYPE(self) = &mrubypp::bind_class<Point>::data_type;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
static mrb_value point_native_div(mrb_state *mrb, mrb_value self) {
|
static mrb_value point_native_div(mrb_state *mrb, mrb_value self) {
|
||||||
auto point = mrubypp::bind_class<Point>::get_this(mrb, self);
|
auto point = mrubypp::bind_class<Point>::get_this(mrb, self);
|
||||||
auto divisor = mrubypp::converter<int>::from_mrb(mrb, mrb_get_arg1(mrb));
|
auto divisor = mrubypp::converter<int>::from_mrb(mrb, mrb_get_arg1(mrb));
|
||||||
@@ -61,16 +82,77 @@ template <> struct mrubypp::converter<Point> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Point3D {
|
||||||
|
public:
|
||||||
|
Point3D(int x, int y, int z) : x_(x), y_(y), z_(z) {}
|
||||||
|
|
||||||
|
void set_values(int x, int y, int z) {
|
||||||
|
x_ = x;
|
||||||
|
y_ = y;
|
||||||
|
z_ = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_x() const { return x_; }
|
||||||
|
|
||||||
|
void set_x(int x) { x_ = x; }
|
||||||
|
|
||||||
|
int get_y() const { return y_; }
|
||||||
|
|
||||||
|
void set_y(int y) { y_ = y; }
|
||||||
|
|
||||||
|
int get_z() const { return z_; }
|
||||||
|
|
||||||
|
void set_z(int y) { z_ = y; }
|
||||||
|
|
||||||
|
void add(const Point3D& other) {
|
||||||
|
this->x_ += other.x_;
|
||||||
|
this->y_ += other.y_;
|
||||||
|
this->z_ += other.z_;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int none() { return 1; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
int x_;
|
||||||
|
int y_;
|
||||||
|
int z_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <> struct mrubypp::converter<Point3D> {
|
||||||
|
static mrb_value to_mrb(mrb_state* mrb, const Point3D& var) {
|
||||||
|
mrb_value obj = mrb_obj_value(
|
||||||
|
mrb_data_object_alloc(mrb, mrb->object_class, new Point3D(var),
|
||||||
|
&mrubypp::bind_class<Point3D>::data_type));
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Point3D from_mrb(mrb_state* mrb, mrb_value value) {
|
||||||
|
if (mrb_type(value) == MRB_TT_DATA) {
|
||||||
|
Point3D* point = static_cast<Point3D*>(DATA_PTR(value));
|
||||||
|
return *point;
|
||||||
|
}
|
||||||
|
return Point3D(0, 0,0 );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
TEST_CASE("bind_class", "[class]") {
|
TEST_CASE("bind_class", "[class]") {
|
||||||
mrubypp::engine engine;
|
mrubypp::engine engine;
|
||||||
mrubypp::bind_class<Point>(engine.get_mrb(), "Point")
|
mrubypp::bind_class<Point>(engine.get_mrb(), "Point")
|
||||||
.def_constructor<int, int>()
|
.def_constructor(point_native_init, MRB_ARGS_OPT(2))
|
||||||
.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_property("y", &Point::get_y, &Point::set_y)
|
||||||
.def_native("div", point_native_div, MRB_ARGS_REQ(1));
|
.def_native("div", point_native_div, MRB_ARGS_REQ(1));
|
||||||
|
|
||||||
|
mrubypp::bind_class<Point3D>(engine.get_mrb(), "Point3D")
|
||||||
|
.def_constructor<int, int, int>()
|
||||||
|
.def_property("x", &Point3D::get_x, &Point3D::set_x)
|
||||||
|
.def_property("y", &Point3D::get_y, &Point3D::set_y)
|
||||||
|
.def_property("z", &Point3D::get_z, &Point3D::set_z);
|
||||||
|
|
||||||
engine.load(R"(
|
engine.load(R"(
|
||||||
def test_method()
|
def test_method()
|
||||||
p = Point.new(3, 4)
|
p = Point.new(3, 4)
|
||||||
@@ -91,6 +173,14 @@ TEST_CASE("bind_class", "[class]") {
|
|||||||
def test_class_method()
|
def test_class_method()
|
||||||
return Point::none()
|
return Point::none()
|
||||||
end
|
end
|
||||||
|
def test_class_init()
|
||||||
|
return Point.new(10)
|
||||||
|
end
|
||||||
|
def test_point3d_init()
|
||||||
|
p = Point.new(10, 11)
|
||||||
|
p3d = Point3D.new(p.x, p.y, 5)
|
||||||
|
return p3d
|
||||||
|
end
|
||||||
)");
|
)");
|
||||||
|
|
||||||
SECTION("test_method") {
|
SECTION("test_method") {
|
||||||
@@ -115,4 +205,17 @@ TEST_CASE("bind_class", "[class]") {
|
|||||||
auto result = engine.call<int>("test_class_method");
|
auto result = engine.call<int>("test_class_method");
|
||||||
REQUIRE(result == 1);
|
REQUIRE(result == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("test_class_init") {
|
||||||
|
auto result = engine.call<Point>("test_class_init");
|
||||||
|
REQUIRE(result.get_x() == 10);
|
||||||
|
REQUIRE(result.get_y() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("test_point3d_init") {
|
||||||
|
auto result = engine.call<Point3D>("test_point3d_init");
|
||||||
|
REQUIRE(result.get_x() == 10);
|
||||||
|
REQUIRE(result.get_y() == 11);
|
||||||
|
REQUIRE(result.get_z() == 5);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user