Add support for calling wren methods from c++ using call()
This commit is contained in:
parent
2755371792
commit
df52fe0fba
5 changed files with 117 additions and 11 deletions
14
src/main.cpp
14
src/main.cpp
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VM::call (const Handle& method) {
|
||||||
|
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 {
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue