better call template & move to include/murbypp dir & fix test namepsace
Some checks failed
ubuntu / Explore-Gitea-Actions (push) Failing after 1m47s
Some checks failed
ubuntu / Explore-Gitea-Actions (push) Failing after 1m47s
This commit is contained in:
@@ -14,13 +14,12 @@ if (MSVC)
|
|||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
add_library(mrubypp INTERFACE
|
add_library(mrubypp INTERFACE
|
||||||
engine.h
|
include/mrubypp/engine.h
|
||||||
converters.h
|
include/mrubypp/converters.h
|
||||||
arena_guard.h
|
include/mrubypp/arena_guard.h
|
||||||
bind_class.h)
|
include/mrubypp/bind_class.h)
|
||||||
|
|
||||||
|
target_include_directories(mrubypp INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include)
|
||||||
include_directories(${CMAKE_CURRENT_LIST_DIR})
|
|
||||||
|
|
||||||
if (${MRUBYPP_BUILD_TEST})
|
if (${MRUBYPP_BUILD_TEST})
|
||||||
if (NOT DEFINED mruby_ROOT)
|
if (NOT DEFINED mruby_ROOT)
|
||||||
|
|||||||
54
engine.h
54
engine.h
@@ -1,54 +0,0 @@
|
|||||||
#ifndef MRUBYPP_H
|
|
||||||
#define MRUBYPP_H
|
|
||||||
|
|
||||||
#include "arena_guard.h"
|
|
||||||
#include "bind_class.h"
|
|
||||||
#include "converters.h"
|
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
#include <mruby.h>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include <mruby/compile.h>
|
|
||||||
|
|
||||||
namespace mrubypp {
|
|
||||||
class engine {
|
|
||||||
public:
|
|
||||||
engine() { mrb_ = mrb_open(); }
|
|
||||||
~engine() { mrb_close(mrb_); }
|
|
||||||
void load(const std::string &str) {
|
|
||||||
if (!mrb_)
|
|
||||||
return;
|
|
||||||
mrb_load_string(mrb_, str.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T> T call(const std::string &funcName) {
|
|
||||||
arena_guard guard(mrb_);
|
|
||||||
mrb_value result =
|
|
||||||
mrb_funcall(mrb_, mrb_top_self(mrb_), funcName.data(), 0);
|
|
||||||
return converter<T>::from_mrb(mrb_, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, typename... Args>
|
|
||||||
T call(const std::string &funcName, Args... args) {
|
|
||||||
arena_guard guard(mrb_);
|
|
||||||
mrb_value argv[] = {converter<Args>::to_mrb(mrb_, args)...};
|
|
||||||
mrb_sym sym = mrb_intern_cstr(mrb_, funcName.data());
|
|
||||||
mrb_value result =
|
|
||||||
mrb_funcall_argv(mrb_, mrb_top_self(mrb_), sym, sizeof...(Args), argv);
|
|
||||||
return converter<T>::from_mrb(mrb_, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
class_builder<T> class_builder(const std::string &class_name) {
|
|
||||||
return class_builder<T>(mrb_, class_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] mrb_state *get_mrb() const { return mrb_; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
mrb_state *mrb_;
|
|
||||||
};
|
|
||||||
} // namespace mrubypp
|
|
||||||
|
|
||||||
#endif // MRUBYPP_H
|
|
||||||
@@ -4,12 +4,8 @@
|
|||||||
#include "arena_guard.h"
|
#include "arena_guard.h"
|
||||||
#include "converters.h"
|
#include "converters.h"
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
#include <map>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <type_traits>
|
#include <tuple>
|
||||||
#include <utility>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include <mruby/class.h>
|
#include <mruby/class.h>
|
||||||
#include <mruby/data.h>
|
#include <mruby/data.h>
|
||||||
@@ -129,7 +125,7 @@ struct function_wrapper {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T> class class_builder;
|
template <typename T> class bind_class;
|
||||||
|
|
||||||
template <typename T, typename... Args> struct constructor_wrapper {
|
template <typename T, typename... Args> struct constructor_wrapper {
|
||||||
static mrb_value wrapper(mrb_state *mrb, mrb_value self) {
|
static mrb_value wrapper(mrb_state *mrb, mrb_value self) {
|
||||||
@@ -137,16 +133,16 @@ template <typename T, typename... Args> struct constructor_wrapper {
|
|||||||
T *instance = std::apply([](Args... args) { return new T(args...); }, args);
|
T *instance = std::apply([](Args... args) { return new T(args...); }, args);
|
||||||
|
|
||||||
DATA_PTR(self) = instance;
|
DATA_PTR(self) = instance;
|
||||||
DATA_TYPE(self) = &class_builder<T>::data_type;
|
DATA_TYPE(self) = &bind_class<T>::data_type;
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T> class class_builder {
|
template <typename T> class bind_class {
|
||||||
public:
|
public:
|
||||||
static const struct mrb_data_type data_type;
|
static const struct mrb_data_type data_type;
|
||||||
|
|
||||||
class_builder(mrb_state *mrb, std::string name)
|
bind_class(mrb_state *mrb, std::string name)
|
||||||
: mrb_(mrb), name_(std::move(name)) {
|
: mrb_(mrb), name_(std::move(name)) {
|
||||||
rclass_ = mrb_define_class(mrb_, name_.c_str(), mrb_->object_class);
|
rclass_ = mrb_define_class(mrb_, name_.c_str(), mrb_->object_class);
|
||||||
MRB_SET_INSTANCE_TT(rclass_, MRB_TT_DATA);
|
MRB_SET_INSTANCE_TT(rclass_, MRB_TT_DATA);
|
||||||
@@ -161,7 +157,7 @@ public:
|
|||||||
MRB_ARGS_ANY());
|
MRB_ARGS_ANY());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args> class_builder &def_constructor() {
|
template <typename... Args> bind_class &def_constructor() {
|
||||||
mrb_define_method(mrb_, rclass_, "initialize",
|
mrb_define_method(mrb_, rclass_, "initialize",
|
||||||
&constructor_wrapper<T, Args...>::wrapper,
|
&constructor_wrapper<T, Args...>::wrapper,
|
||||||
MRB_ARGS_REQ(sizeof...(Args)));
|
MRB_ARGS_REQ(sizeof...(Args)));
|
||||||
@@ -169,8 +165,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename Ret, typename... MethodArgs>
|
template <typename Ret, typename... MethodArgs>
|
||||||
class_builder &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...>;
|
||||||
@@ -188,8 +184,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename Ret, typename... MethodArgs>
|
template <typename Ret, typename... MethodArgs>
|
||||||
class_builder &def_method(const std::string &name,
|
bind_class &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());
|
||||||
using wrap = const_method_wrapper<T, Ret, MethodArgs...>;
|
using wrap = const_method_wrapper<T, Ret, MethodArgs...>;
|
||||||
|
|
||||||
@@ -206,8 +202,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename Ret, typename... FuncArgs>
|
template <typename Ret, typename... FuncArgs>
|
||||||
class_builder &def_class_method(const std::string &name,
|
bind_class &def_class_method(const std::string &name,
|
||||||
Ret (*func)(FuncArgs...)) {
|
Ret (*func)(FuncArgs...)) {
|
||||||
using wrap = function_wrapper<T, Ret, FuncArgs...>;
|
using wrap = function_wrapper<T, Ret, FuncArgs...>;
|
||||||
mrb_value env[] = {
|
mrb_value env[] = {
|
||||||
mrb_cptr_value(mrb_, (void *)func),
|
mrb_cptr_value(mrb_, (void *)func),
|
||||||
@@ -226,15 +222,15 @@ public:
|
|||||||
|
|
||||||
// get set
|
// get set
|
||||||
template <typename Ret>
|
template <typename Ret>
|
||||||
class_builder &def_property(const std::string &name, Ret (T::*getter)() const,
|
bind_class &def_property(const std::string &name, 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
class_builder &def_native(const std::string &name, mrb_func_t func,
|
bind_class &def_native(const std::string &name, mrb_func_t func,
|
||||||
mrb_aspec aspec = MRB_ARGS_ANY()) {
|
mrb_aspec aspec = MRB_ARGS_ANY()) {
|
||||||
mrb_define_method(mrb_, rclass_, name.c_str(), func, aspec);
|
mrb_define_method(mrb_, rclass_, name.c_str(), func, aspec);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -262,8 +258,8 @@ private:
|
|||||||
std::string name_;
|
std::string name_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T> const struct mrb_data_type class_builder<T>::data_type = {
|
template <typename T> const struct mrb_data_type bind_class<T>::data_type = {
|
||||||
typeid(T).name(), class_builder<T>::free_instance
|
typeid(T).name(), bind_class<T>::free_instance
|
||||||
};
|
};
|
||||||
} // namespace mrubypp
|
} // namespace mrubypp
|
||||||
|
|
||||||
60
include/mrubypp/engine.h
Normal file
60
include/mrubypp/engine.h
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
#ifndef MRUBYPP_H
|
||||||
|
#define MRUBYPP_H
|
||||||
|
|
||||||
|
#include "arena_guard.h"
|
||||||
|
#include "converters.h"
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <mruby.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <mruby/compile.h>
|
||||||
|
|
||||||
|
namespace mrubypp {
|
||||||
|
class engine {
|
||||||
|
public:
|
||||||
|
engine() { mrb_ = mrb_open(); }
|
||||||
|
~engine() { mrb_close(mrb_); }
|
||||||
|
void load(const std::string &str) {
|
||||||
|
if (!mrb_)
|
||||||
|
return;
|
||||||
|
mrb_load_string(mrb_, str.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename... Args>
|
||||||
|
typename std::enable_if<!std::is_same<T, void>::value, T>::type
|
||||||
|
call(const std::string &funcName, Args... args) {
|
||||||
|
arena_guard guard(mrb_);
|
||||||
|
if constexpr (sizeof...(Args) > 0) {
|
||||||
|
mrb_value argv[] = {converter<Args>::to_mrb(mrb_, args)...};
|
||||||
|
mrb_sym sym = mrb_intern_cstr(mrb_, funcName.data());
|
||||||
|
mrb_value result = mrb_funcall_argv(mrb_, mrb_top_self(mrb_), sym,
|
||||||
|
sizeof...(Args), argv);
|
||||||
|
return converter<T>::from_mrb(mrb_, result);
|
||||||
|
}
|
||||||
|
mrb_value result =
|
||||||
|
mrb_funcall(mrb_, mrb_top_self(mrb_), funcName.data(), 0);
|
||||||
|
return converter<T>::from_mrb(mrb_, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T = void, typename... Args>
|
||||||
|
typename std::enable_if<std::is_same<T, void>::value, T>::type
|
||||||
|
call(const std::string &funcName, Args... args) {
|
||||||
|
if constexpr (sizeof...(Args) > 0) {
|
||||||
|
arena_guard guard(mrb_);
|
||||||
|
mrb_value argv[] = {converter<Args>::to_mrb(mrb_, args)...};
|
||||||
|
mrb_sym sym = mrb_intern_cstr(mrb_, funcName.data());
|
||||||
|
mrb_funcall_argv(mrb_, mrb_top_self(mrb_), sym, sizeof...(Args), argv);
|
||||||
|
} else {
|
||||||
|
mrb_funcall(mrb_, mrb_top_self(mrb_), funcName.data(), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] mrb_state *get_mrb() const { return mrb_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
mrb_state *mrb_;
|
||||||
|
};
|
||||||
|
} // namespace mrubypp
|
||||||
|
|
||||||
|
#endif // MRUBYPP_H
|
||||||
@@ -4,7 +4,8 @@
|
|||||||
|
|
||||||
#include <catch2/catch_all.hpp>
|
#include <catch2/catch_all.hpp>
|
||||||
|
|
||||||
#include "engine.h"
|
#include <mrubypp/bind_class.h>
|
||||||
|
#include <mrubypp/engine.h>
|
||||||
|
|
||||||
class Point {
|
class Point {
|
||||||
public:
|
public:
|
||||||
@@ -36,18 +37,18 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
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_class_builder<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));
|
||||||
point->set_x(point->get_x() / divisor);
|
point->set_x(point->get_x() / divisor);
|
||||||
point->set_y(point->get_y() / divisor);
|
point->set_y(point->get_y() / divisor);
|
||||||
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),
|
||||||
&mrubypp_class_builder<Point>::data_type));
|
&mrubypp::bind_class<Point>::data_type));
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,9 +61,9 @@ template <> struct mrubypp_converter<Point> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_CASE("Point", "[class]") {
|
TEST_CASE("bind_class", "[class]") {
|
||||||
engine engine;
|
mrubypp::engine engine;
|
||||||
engine.class_builder<Point>("Point")
|
mrubypp::bind_class<Point>(engine.get_mrb(), "Point")
|
||||||
.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)
|
||||||
|
|||||||
@@ -7,10 +7,10 @@
|
|||||||
|
|
||||||
#include <catch2/catch_all.hpp>
|
#include <catch2/catch_all.hpp>
|
||||||
|
|
||||||
#include "engine.h"
|
#include <mrubypp/engine.h>
|
||||||
|
|
||||||
TEST_CASE("none args call", "[engine]") {
|
TEST_CASE("none args call", "[engine]") {
|
||||||
engine engine;
|
mrubypp::engine engine;
|
||||||
engine.load(R"(
|
engine.load(R"(
|
||||||
def get_1()
|
def get_1()
|
||||||
1
|
1
|
||||||
@@ -22,7 +22,7 @@ TEST_CASE("none args call", "[engine]") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("args call", "[engine]") {
|
TEST_CASE("args call", "[engine]") {
|
||||||
engine engine;
|
mrubypp::engine engine;
|
||||||
engine.load(R"(
|
engine.load(R"(
|
||||||
def sort_and_get_first(a)
|
def sort_and_get_first(a)
|
||||||
a.sort!
|
a.sort!
|
||||||
@@ -35,8 +35,20 @@ TEST_CASE("args call", "[engine]") {
|
|||||||
REQUIRE(b == 1);
|
REQUIRE(b == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("void call", "[engine]") {
|
||||||
|
mrubypp::engine engine;
|
||||||
|
engine.load(R"(
|
||||||
|
def no_return_puts(a)
|
||||||
|
puts a
|
||||||
|
end
|
||||||
|
)");
|
||||||
|
|
||||||
|
std::vector<int> a{3, 1, 2};
|
||||||
|
engine.call("no_return_puts", a);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("call benchmark", "[!benchmark]") {
|
TEST_CASE("call benchmark", "[!benchmark]") {
|
||||||
engine engine;
|
mrubypp::engine engine;
|
||||||
engine.load(R"(
|
engine.load(R"(
|
||||||
def get_same(a)
|
def get_same(a)
|
||||||
return a
|
return a
|
||||||
|
|||||||
Reference in New Issue
Block a user