Add support for calling wren methods from c++ using call()

This commit is contained in:
King_DuckZ 2020-04-30 19:58:09 +02:00
parent 2755371792
commit df52fe0fba
5 changed files with 117 additions and 11 deletions

View file

@ -9,9 +9,15 @@ namespace {
R"(class Math { R"(class Math {
construct new() {} construct new() {}
foreign add(a, b) foreign add(a, b)
static sum_params(a,b) {
return a + b
}
} }
System.print("I am running in a VM!") System.print("I am running in a VM!")
var myvar = Math.new() var myvar = Math.new()
var name = "some_test"
var number = 123
myvar.add(5, 6) myvar.add(5, 6)
System.print("Script done") System.print("Script done")
)"; )";
@ -19,11 +25,19 @@ System.print("Script done")
} //unnamed namespace } //unnamed namespace
int main() { int main() {
typedef wren::ModuleAndName MN;
using wren::variables;
std::cout << "hello world\n"; std::cout << "hello world\n";
wren::DefConfiguration config; wren::DefConfiguration config;
wren::VM vm(&config); wren::VM vm(&config);
vm.interpret("my_module", g_script); vm.interpret("my_module", g_script);
std::this_thread::sleep_for(std::chrono::milliseconds(2000)); std::this_thread::sleep_for(std::chrono::milliseconds(2000));
auto vars = variables<std::string, int>(vm, MN{"my_module", "name"}, MN{"my_module","number"});
std::cout << "name = \"" << std::get<0>(vars) << "\", number = " << std::get<1>(vars) << '\n';
const int sum = wren::call<int>(vm, {"my_module", "Math"}, vm.make_call_handle("sum_params(_,_)"), MN{"my_module", "number"}, 90);
std::cout << "wren method returned " << sum << " (expected " << std::get<1>(vars) + 90 << ")\n";
return 0; return 0;
} }

View file

@ -68,6 +68,21 @@ namespace wren {
retval.finalize = funcs.finalize; retval.finalize = funcs.finalize;
return retval; return retval;
} }
void throw_if_err (WrenInterpretResult res, const char* module_name) {
using std::runtime_error;
using std::string;
switch (res) {
case WREN_RESULT_COMPILE_ERROR:
throw runtime_error(string("Compilation of ") + module_name + " has failed");
case WREN_RESULT_RUNTIME_ERROR:
throw runtime_error(string("A runtime error occurred in ") + module_name);
case WREN_RESULT_SUCCESS:
break;
}
}
} //unnamed namespace } //unnamed namespace
struct VM::LocalData { struct VM::LocalData {
@ -138,15 +153,12 @@ namespace wren {
using std::runtime_error; using std::runtime_error;
const WrenInterpretResult res = wrenInterpret(m_local->wvm, module_name, script); const WrenInterpretResult res = wrenInterpret(m_local->wvm, module_name, script);
switch (res) { throw_if_err(res, module_name);
case WREN_RESULT_COMPILE_ERROR: }
throw runtime_error(string("Compilation of ") + module_name + " has failed");
case WREN_RESULT_RUNTIME_ERROR:
throw runtime_error(string("A runtime error occurred in ") + module_name);
case WREN_RESULT_SUCCESS: void VM::call (const Handle& method) {
break; const WrenInterpretResult res = wrenCall(m_local->wvm, method);
} throw_if_err(res, "[wrenCall()]");
} }
void VM::release_handle (Handle& handle) noexcept { void VM::release_handle (Handle& handle) noexcept {

View file

@ -52,7 +52,7 @@ namespace wren {
~VM() noexcept; ~VM() noexcept;
void interpret (const char* module_name, const char* script); void interpret (const char* module_name, const char* script);
void call (Handle& method); void call (const Handle& method);
void release_handle (Handle& handle) noexcept; void release_handle (Handle& handle) noexcept;
void ensure_slots(int num_slots); void ensure_slots(int num_slots);
int slot_count(); int slot_count();
@ -66,7 +66,7 @@ namespace wren {
void set_slot_string (int slot_num, const char* value); void set_slot_string (int slot_num, const char* value);
void set_slot_double (int slot_num, double value); void set_slot_double (int slot_num, double value);
void set_slot_bool (int slot_num, bool value); void set_slot_bool (int slot_num, bool value);
void set_slot_null (int slot_num); void set_slot_null (int slot_num);
void set_slot_bytes (int slot_num, const char* bytes, std::size_t length); void set_slot_bytes (int slot_num, const char* bytes, std::size_t length);
//slot getters //slot getters

View file

@ -8,6 +8,10 @@ namespace wren {
vm.set_slot_bytes(slot_num, beg, std::distance(beg, end)); vm.set_slot_bytes(slot_num, beg, std::distance(beg, end));
} }
void set (VM& vm, int slot_num, const Handle& handle) {
vm.set_slot_handle(handle, slot_num);
}
std::string_view slot_string_view (VM& vm, int slot_num) { std::string_view slot_string_view (VM& vm, int slot_num) {
assert(SlotType::String == vm.slot_type(slot_num)); assert(SlotType::String == vm.slot_type(slot_num));
auto ptr = vm.slot_bytes(slot_num); auto ptr = vm.slot_bytes(slot_num);

View file

@ -4,6 +4,7 @@
#include <string> #include <string>
#include <string_view> #include <string_view>
#include <vector> #include <vector>
#include <type_traits>
namespace wren { namespace wren {
typedef std::tuple<const char*, const char*> ModuleAndName; typedef std::tuple<const char*, const char*> ModuleAndName;
@ -24,11 +25,24 @@ namespace wren {
template <typename... Outs, typename... Params> template <typename... Outs, typename... Params>
#endif #endif
std::tuple<Outs...> variables(VM& vm, Params&&... modules_names); std::tuple<Outs...> variables(VM& vm, Params&&... modules_names);
template <typename R, typename... Args>
R call (VM& vm, const Handle& object, const Handle& method, const Args&... args);
template <typename R, typename... Args>
R call (VM& vm, const ModuleAndName& object, const Handle& method, const Args&... args);
void interpret (VM& vm, const std::string& module_name, const std::string& script); void interpret (VM& vm, const std::string& module_name, const std::string& script);
void set (VM& vm, int slot_num, const char* value);
void set (VM& vm, int slot_num, double value);
void set (VM& vm, int slot_num, bool value);
void set (VM& vm, int slot_num, std::nullptr_t);
void set (VM& vm, int slot_num, const char* bytes, std::size_t length);
void set (VM& vm, int slot_num, const std::string& value); void set (VM& vm, int slot_num, const std::string& value);
void set (VM& vm, int slot_num, std::string_view value); void set (VM& vm, int slot_num, std::string_view value);
void set (VM& vm, int slot_num, const std::vector<char>& value); void set (VM& vm, int slot_num, const std::vector<char>& value);
void set (VM& vm, int slot_num, const char* beg, const char* end); void set (VM& vm, int slot_num, const char* beg, const char* end);
void set (VM& vm, int slot_num, int value);
std::string_view slot_string_view (VM& vm, int slot_num); std::string_view slot_string_view (VM& vm, int slot_num);
template <typename T> T get (VM& vm, int slot_num); template <typename T> T get (VM& vm, int slot_num);
void variable(VM& vm, const ModuleAndName& mod_and_name, int slot); void variable(VM& vm, const ModuleAndName& mod_and_name, int slot);
@ -52,11 +66,32 @@ namespace wren {
static_assert(sizeof...(Params) == sizeof...(Outs), "Expected a module/name pair per requested output"); static_assert(sizeof...(Params) == sizeof...(Outs), "Expected a module/name pair per requested output");
static_assert(sizeof...(Outs) == sizeof...(Indices), "Mismatching index count"); static_assert(sizeof...(Outs) == sizeof...(Indices), "Mismatching index count");
vm.ensure_slots(sizeof...(Outs)); vm.ensure_slots(sizeof...(Params));
(variable(vm, modules_names, Indices), ...); (variable(vm, modules_names, Indices), ...);
return std::tuple<Outs...>(get<Outs>(vm, Indices)...); return std::tuple<Outs...>(get<Outs>(vm, Indices)...);
} }
} }
template <typename T>
inline void set_single_for_call (VM& vm, int slot, const T& value) {
set(vm, slot, value);
}
template <>
inline void set_single_for_call (VM& vm, int slot_num, const Handle& handle) {
vm.set_slot_handle(handle, slot_num);
}
template <>
inline void set_single_for_call (VM& vm, int slot_num, const ModuleAndName& name) {
variable(vm, name, slot_num);
}
template <typename... Args, int... Indices>
inline void set_for_call (std::integer_sequence<int, Indices...>, VM& vm, const Args&... args) {
vm.ensure_slots(sizeof...(Args));
(set_single_for_call(vm, Indices + 1, args), ...);
}
} //namespace detail } //namespace detail
#if __cpp_concepts >= 201907 #if __cpp_concepts >= 201907
@ -72,6 +107,26 @@ namespace wren {
return vm.interpret(module_name.c_str(), script.c_str()); return vm.interpret(module_name.c_str(), script.c_str());
} }
inline void set (VM& vm, int slot_num, const char* value) {
vm.set_slot_string(slot_num, value);
}
inline void set (VM& vm, int slot_num, double value) {
vm.set_slot_double(slot_num, value);
}
inline void set (VM& vm, int slot_num, bool value) {
vm.set_slot_bool(slot_num, value);
}
inline void set (VM& vm, int slot_num, std::nullptr_t) {
vm.set_slot_null(slot_num);
}
inline void set (VM& vm, int slot_num, const char* bytes, std::size_t length) {
vm.set_slot_bytes(slot_num, bytes, length);
}
inline void set (VM& vm, int slot_num, const std::string& value) { inline void set (VM& vm, int slot_num, const std::string& value) {
vm.set_slot_string(slot_num, value.c_str()); vm.set_slot_string(slot_num, value.c_str());
} }
@ -83,4 +138,25 @@ namespace wren {
inline void set (VM& vm, int slot_num, const std::vector<char>& value) { inline void set (VM& vm, int slot_num, const std::vector<char>& value) {
vm.set_slot_bytes(slot_num, value.data(), value.size()); vm.set_slot_bytes(slot_num, value.data(), value.size());
} }
inline void set (VM& vm, int slot_num, int value) {
vm.set_slot_double(slot_num, static_cast<double>(value));
}
template <typename R, typename... Args>
inline R call (VM& vm, const Handle& object, const Handle& method, const Args&... args) {
detail::set_for_call<Args...>(std::make_integer_sequence<int, sizeof...(Args)>(), vm, args...);
vm.call(method);
if constexpr (not std::is_same<void, R>::value) {
return get<R>(vm, 0);
}
}
template <typename R, typename... Args>
inline R call (VM& vm, const ModuleAndName& object, const Handle& method, const Args&... args) {
vm.ensure_slots(sizeof...(args) + 1);
variable(vm, object, 0);
Handle obj_handle = vm.slot_handle(0);
return call<R, Args...>(vm, obj_handle, method, args...);
}
} //namespace wren } //namespace wren