Add support for object parameters to Wren calls
This commit is contained in:
parent
b00bd59027
commit
05298b6111
9 changed files with 282 additions and 37 deletions
175
examples/call_cpp/main.cpp
Normal file
175
examples/call_cpp/main.cpp
Normal file
|
@ -0,0 +1,175 @@
|
||||||
|
/* Copyright 2020-2024, Michele Santullo
|
||||||
|
* This file is part of wrenpp.
|
||||||
|
*
|
||||||
|
* Wrenpp is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Wrenpp is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with wrenpp. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "wrenpp/vm_fun.hpp"
|
||||||
|
#include "wrenpp/def_configuration.hpp"
|
||||||
|
#include "wrenpp/callback_manager.hpp"
|
||||||
|
#include "wrenpp/class_manager.hpp"
|
||||||
|
#include <chrono>
|
||||||
|
#include <thread>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
constexpr char g_module_a[] =
|
||||||
|
"foreign class ClassA {" R"script(
|
||||||
|
construct new(msg) {
|
||||||
|
System.print("Wren ClassA constructed")
|
||||||
|
}
|
||||||
|
|
||||||
|
foreign say_hi()
|
||||||
|
}
|
||||||
|
)script";
|
||||||
|
|
||||||
|
constexpr char g_module_b[] = ""
|
||||||
|
R"script(
|
||||||
|
import "module_a" for ClassA
|
||||||
|
|
||||||
|
foreign class ClassB {
|
||||||
|
construct new(nickname) {
|
||||||
|
System.print("Wren ClassB constructed")
|
||||||
|
}
|
||||||
|
|
||||||
|
do_action(obj_a, times) {
|
||||||
|
System.print("Wren ClassB is doing its action %(times) times...")
|
||||||
|
for (z in 1..times) {
|
||||||
|
obj_a.say_hi()
|
||||||
|
}
|
||||||
|
greeting_message("John", "Doe", "\\(O.O)/")
|
||||||
|
}
|
||||||
|
|
||||||
|
foreign greeting_message(first_name, family_name, emoji)
|
||||||
|
}
|
||||||
|
)script";
|
||||||
|
|
||||||
|
//This is three examples in one:
|
||||||
|
//1. instantiate ClassA in Wren and pass it to do_action() which is a
|
||||||
|
// non-foreign method in wren
|
||||||
|
//2. instantiate ClassA in C++, have C++ invoke the non-foreign method
|
||||||
|
// do_action() on the object obj_b from the previous execution and pass the
|
||||||
|
// C++ instance of ClassA to it
|
||||||
|
//3. instantiate ClassB in C++, have C++ invoke the non-foreign method
|
||||||
|
// do_action() on it and pass the same ClassA instance from the previous
|
||||||
|
// step to it
|
||||||
|
constexpr char g_script[] = ""
|
||||||
|
R"script(
|
||||||
|
import "module_a" for ClassA
|
||||||
|
import "module_b" for ClassB
|
||||||
|
|
||||||
|
var obj_b = ClassB.new("TheWren")
|
||||||
|
obj_b.do_action(ClassA.new("instanciated from script"), 2)
|
||||||
|
obj_b.greeting_message("Jane", "Doe", "ʕ·͡ᴥ·ʔ")
|
||||||
|
)script";
|
||||||
|
|
||||||
|
class MyWrenConfig : public wren::DefConfiguration {
|
||||||
|
public:
|
||||||
|
char* load_module_fn (wren::VM* vm, std::string_view module_name) {
|
||||||
|
if (module_name == "module_a")
|
||||||
|
return copied(g_module_a, sizeof(g_module_a));
|
||||||
|
else if (module_name == "module_b")
|
||||||
|
return copied(g_module_b, sizeof(g_module_b));
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_module_complete_fn (wren::VM* vm, std::string_view module_name, char* buff) {
|
||||||
|
static_cast<void>(vm);
|
||||||
|
static_cast<void>(module_name);
|
||||||
|
delete[] buff;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
char* copied (const char* source, std::size_t len) {
|
||||||
|
char* const buff = new char[len];
|
||||||
|
std::copy(source, source + len / sizeof(source[0]), buff);
|
||||||
|
return buff;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ClassA {
|
||||||
|
explicit ClassA (std::string msg) : m_message(msg) {
|
||||||
|
std::cout << "C++ ClassA constructed\n";
|
||||||
|
}
|
||||||
|
ClassA (const ClassA&) = delete;
|
||||||
|
ClassA (ClassA&&) = delete;
|
||||||
|
|
||||||
|
void say_hi() {
|
||||||
|
std::cout << "C++ ClassA says \"" << m_message << "\"!\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string m_message;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ClassB {
|
||||||
|
public:
|
||||||
|
explicit ClassB (std::string nickname) : m_nickname(nickname) {
|
||||||
|
std::cout << "C++ ClassB constructed\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassB (const ClassB&) = delete;
|
||||||
|
ClassB (ClassB&&) = delete;
|
||||||
|
|
||||||
|
void greeting_message (
|
||||||
|
std::string_view first_name,
|
||||||
|
const char* family_name,
|
||||||
|
const std::string& emoji
|
||||||
|
) {
|
||||||
|
std::cout << "C++ ClassB says \"hello " << first_name << " '" <<
|
||||||
|
m_nickname << "' " << family_name << "\" " << emoji << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_nickname;
|
||||||
|
};
|
||||||
|
} //unnamed namespace
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
using wren::make_function_bindable;
|
||||||
|
using wren::make_foreign_class;
|
||||||
|
using wren::make_wren_object;
|
||||||
|
|
||||||
|
//We need a custom one to deal with custom module loading for
|
||||||
|
//module_a and module_b
|
||||||
|
MyWrenConfig config;
|
||||||
|
wren::VM vm(&config, nullptr);
|
||||||
|
|
||||||
|
|
||||||
|
vm.callback_manager()
|
||||||
|
.add_callback(false, "module_a", "ClassA", "say_hi()", make_function_bindable<&ClassA::say_hi>)
|
||||||
|
.add_callback(false, "module_b", "ClassB", "greeting_message(_,_,_)", make_function_bindable<&ClassB::greeting_message>)
|
||||||
|
;
|
||||||
|
vm.class_manager()
|
||||||
|
.add_class_maker("module_b", "ClassB", make_foreign_class<ClassB, std::string>)
|
||||||
|
.add_class_maker("module_a", "ClassA", make_foreign_class<ClassA, std::string>)
|
||||||
|
;
|
||||||
|
|
||||||
|
//Example 1: invoke obj_b.do_action() from Wren passing an obj_a that's
|
||||||
|
//also instantiated from within the Wren script
|
||||||
|
vm.interpret("main", g_script);
|
||||||
|
|
||||||
|
//Example 2: invoke obj_b.do_action() from C++ passing a new obj_a which
|
||||||
|
//is instantiated from C++
|
||||||
|
wren::ForeignObject<ClassA> obj_a = make_wren_object<ClassA>(vm, wren::MN<"module_a", "ClassA">, "instantiated from c++");
|
||||||
|
wren::call<void>(vm, wren::MN<"main", "obj_b">, "do_action", obj_a, 3);
|
||||||
|
|
||||||
|
//Example 3: invoke obj_b.do_action() from C++, where obj_b is also
|
||||||
|
//instantiated from C++, and pass the C++ obj_a instance to it
|
||||||
|
auto obj_b = make_wren_object<ClassB>(vm, wren::MN<"module_b", "ClassB">, "TheCpp");
|
||||||
|
wren::call<void>(vm, obj_b, "do_action", obj_a, 4);
|
||||||
|
|
||||||
|
std::cout << "Quitting in 1 sec" << std::endl;
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
|
||||||
|
return 0;
|
||||||
|
}
|
5
examples/call_cpp/meson.build
Normal file
5
examples/call_cpp/meson.build
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
executable('call_cpp',
|
||||||
|
'main.cpp',
|
||||||
|
dependencies: wrenpp_dep,
|
||||||
|
install: false,
|
||||||
|
)
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright 2020-2022, Michele Santullo
|
/* Copyright 2020-2024, Michele Santullo
|
||||||
* This file is part of wrenpp.
|
* This file is part of wrenpp.
|
||||||
*
|
*
|
||||||
* Wrenpp is free software: you can redistribute it and/or modify
|
* Wrenpp is free software: you can redistribute it and/or modify
|
||||||
|
@ -63,8 +63,6 @@ void user_get_env (wren::VM& vm, wren::ModuleAndName) {
|
||||||
} //unnamed namespace
|
} //unnamed namespace
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
//typedef wren::ModuleAndName MN;
|
|
||||||
|
|
||||||
wren::DefConfiguration config;
|
wren::DefConfiguration config;
|
||||||
wren::VM vm(&config, nullptr);
|
wren::VM vm(&config, nullptr);
|
||||||
vm.callback_manager().add_callback(true, "main", "User", "get_env(_)", [](){return &user_get_env;});
|
vm.callback_manager().add_callback(true, "main", "User", "get_env(_)", [](){return &user_get_env;});
|
||||||
|
|
|
@ -2,3 +2,4 @@ subdir('dieroll')
|
||||||
subdir('greet')
|
subdir('greet')
|
||||||
subdir('calendar')
|
subdir('calendar')
|
||||||
subdir('math_vector')
|
subdir('math_vector')
|
||||||
|
subdir('call_cpp')
|
||||||
|
|
63
include/wrenpp/detail/foreign_object.hpp
Normal file
63
include/wrenpp/detail/foreign_object.hpp
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
/* Copyright 2020-2024, Michele Santullo
|
||||||
|
* This file is part of wrenpp.
|
||||||
|
*
|
||||||
|
* Wrenpp is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Wrenpp is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with wrenpp. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "wrenpp/handle.hpp"
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace wren {
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class ForeignObject {
|
||||||
|
public:
|
||||||
|
ForeignObject() = default;
|
||||||
|
ForeignObject (std::nullptr_t) : ForeignObject() {}
|
||||||
|
ForeignObject (T* obj, Handle&& handle);
|
||||||
|
~ForeignObject() noexcept = default;
|
||||||
|
|
||||||
|
void set_to_slot (int num);
|
||||||
|
T& object() { return *m_object; }
|
||||||
|
const T& object() const { return *m_object; }
|
||||||
|
Handle& handle() { return m_handle; }
|
||||||
|
const Handle& handle() const { return m_handle; }
|
||||||
|
bool is_valid() const { return nullptr != m_object; }
|
||||||
|
|
||||||
|
operator T&() { return object(); }
|
||||||
|
operator const T&() const { return object(); }
|
||||||
|
operator Handle&() { return handle(); }
|
||||||
|
operator const Handle&() const { return handle(); }
|
||||||
|
bool operator!= (std::nullptr_t) const { return nullptr != m_object; }
|
||||||
|
bool operator== (std::nullptr_t) const { return nullptr == m_object; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Handle m_handle;
|
||||||
|
T* m_object{nullptr};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline ForeignObject<T>::ForeignObject (T* obj, Handle&& handle) :
|
||||||
|
m_handle(std::move(handle)),
|
||||||
|
m_object(obj)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline void ForeignObject<T>::set_to_slot (int num) {
|
||||||
|
m_handle.set_to_slot(num);
|
||||||
|
}
|
||||||
|
|
||||||
|
} //namespace wren
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright 2020-2022, Michele Santullo
|
/* Copyright 2020-2024, Michele Santullo
|
||||||
* This file is part of wrenpp.
|
* This file is part of wrenpp.
|
||||||
*
|
*
|
||||||
* Wrenpp is free software: you can redistribute it and/or modify
|
* Wrenpp is free software: you can redistribute it and/or modify
|
||||||
|
@ -18,6 +18,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../vm.hpp"
|
#include "../vm.hpp"
|
||||||
|
#include "../handle.hpp"
|
||||||
#include "module_and_name.hpp"
|
#include "module_and_name.hpp"
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -87,6 +88,8 @@ namespace wren {
|
||||||
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);
|
void set (VM& vm, int slot_num, int value);
|
||||||
void set (VM& vm, int slot_num, std::size_t value);
|
void set (VM& vm, int slot_num, std::size_t value);
|
||||||
|
void set (VM& vm, int slot_num, const Handle& handle);
|
||||||
|
void set (VM& vm, int slot_num, const ModuleAndName& name);
|
||||||
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> detail::GetTypeToRetType_t<T> get (VM& vm, int slot_num);
|
template <typename T> detail::GetTypeToRetType_t<T> get (VM& vm, int slot_num);
|
||||||
template <typename T> T* foreign (VM& vm, int slot_num);
|
template <typename T> T* foreign (VM& vm, int slot_num);
|
||||||
|
@ -138,6 +141,14 @@ namespace wren {
|
||||||
vm.set_slot_double(slot_num, static_cast<double>(value));
|
vm.set_slot_double(slot_num, static_cast<double>(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void set (VM& vm, int slot_num, const Handle& handle) {
|
||||||
|
vm.set_slot_handle(handle, slot_num);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void set (VM& vm, int slot_num, const ModuleAndName& name) {
|
||||||
|
vm.variable_or_throw(name.module_name_char(), name.class_name_char(), slot_num);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline T* foreign (VM& vm, int slot_num) {
|
inline T* foreign (VM& vm, int slot_num) {
|
||||||
T* obj = static_cast<T*>(vm.slot_foreign(slot_num));
|
T* obj = static_cast<T*>(vm.slot_foreign(slot_num));
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright 2020-2022, Michele Santullo
|
/* Copyright 2020-2024, Michele Santullo
|
||||||
* This file is part of wrenpp.
|
* This file is part of wrenpp.
|
||||||
*
|
*
|
||||||
* Wrenpp is free software: you can redistribute it and/or modify
|
* Wrenpp is free software: you can redistribute it and/or modify
|
||||||
|
@ -42,6 +42,8 @@ namespace wren {
|
||||||
operator WrenHandle*() const { return m_handle; }
|
operator WrenHandle*() const { return m_handle; }
|
||||||
operator bool() const { return nullptr != m_handle; }
|
operator bool() const { return nullptr != m_handle; }
|
||||||
|
|
||||||
|
void set_to_slot (int num);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
WrenHandle* m_handle;
|
WrenHandle* m_handle;
|
||||||
VM* m_vm;
|
VM* m_vm;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright 2020-2022, Michele Santullo
|
/* Copyright 2020-2024, Michele Santullo
|
||||||
* This file is part of wrenpp.
|
* This file is part of wrenpp.
|
||||||
*
|
*
|
||||||
* Wrenpp is free software: you can redistribute it and/or modify
|
* Wrenpp is free software: you can redistribute it and/or modify
|
||||||
|
@ -26,6 +26,7 @@
|
||||||
#include "detail/construct_foreign_class.hpp"
|
#include "detail/construct_foreign_class.hpp"
|
||||||
#include "detail/setters_getters.hpp"
|
#include "detail/setters_getters.hpp"
|
||||||
#include "detail/wren_class_name_from_type.hpp"
|
#include "detail/wren_class_name_from_type.hpp"
|
||||||
|
#include "detail/foreign_object.hpp"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
@ -46,11 +47,11 @@ namespace wren {
|
||||||
R call (VM& vm, ModuleAndName object, const char (&method)[N], const Args&... args);
|
R call (VM& vm, ModuleAndName object, const char (&method)[N], const Args&... args);
|
||||||
|
|
||||||
template <typename T, typename... Args>
|
template <typename T, typename... Args>
|
||||||
T* make_wren_object(VM& vm, ModuleAndName mn, Args&&... args);
|
ForeignObject<T> make_wren_object(VM& vm, ModuleAndName mn, Args&&... args);
|
||||||
|
|
||||||
#if defined(WRENPP_WITH_NAME_GUESSING)
|
#if defined(WRENPP_WITH_NAME_GUESSING)
|
||||||
template <typename T, dhandy::bt::string Mod, typename... Args>
|
template <typename T, dhandy::bt::string Mod, typename... Args>
|
||||||
T* make_wren_object(VM& vm, Args&&... args);
|
ForeignObject<T> make_wren_object(VM& vm, Args&&... args);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
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);
|
||||||
|
@ -61,28 +62,13 @@ namespace wren {
|
||||||
void abort_fiber_with_error (VM& vm, int slot, std::string_view message);
|
void abort_fiber_with_error (VM& vm, int slot, std::string_view message);
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Sets arguments so wren is ready to perform a function call. It doesn't
|
//Sets arguments so wren is ready to perform a function call. It doesn't
|
||||||
//touch at slot 0, so eventual objects for method calls must be set
|
//touch at slot 0, so eventual objects for method calls must be set
|
||||||
//manually
|
//manually
|
||||||
template <typename... Args, int... Indices>
|
template <typename... Args, int... Indices>
|
||||||
inline void set_for_call (std::integer_sequence<int, Indices...>, VM& vm, const Args&... args) {
|
inline void set_for_call (std::integer_sequence<int, Indices...>, VM& vm, const Args&... args) {
|
||||||
vm.ensure_slots(sizeof...(Args));
|
vm.ensure_slots(sizeof...(Args));
|
||||||
(set_single_for_call(vm, Indices + 1, args), ...);
|
(set(vm, Indices + 1, args), ...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <auto V>
|
template <auto V>
|
||||||
|
@ -145,7 +131,7 @@ namespace wren {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ModuleAndName wren_name = wren_class_name_from_type<R>(vm);
|
ModuleAndName wren_name = wren_class_name_from_type<R>(vm);
|
||||||
R* const new_object = make_wren_object<R>(vm, wren_name, std::move(ret));
|
ForeignObject<R> new_object = make_wren_object<R>(vm, wren_name, std::move(ret));
|
||||||
static_cast<void>(new_object);
|
static_cast<void>(new_object);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -197,15 +183,13 @@ namespace wren {
|
||||||
inline R call (VM& vm, const Handle& object, const char (&method)[N], const Args&... args) {
|
inline R call (VM& vm, const Handle& object, const char (&method)[N], const Args&... args) {
|
||||||
using dhandy::bt::string;
|
using dhandy::bt::string;
|
||||||
|
|
||||||
const constexpr char dummy_name_buff[N] = {0};
|
const constexpr auto params = string("(") +
|
||||||
const constexpr auto params = string<N, char>(dummy_name_buff) +
|
|
||||||
string("(") +
|
|
||||||
((static_cast<void>(args), string(",_")) + ... + string("")).template substr<1>() +
|
((static_cast<void>(args), string(",_")) + ... + string("")).template substr<1>() +
|
||||||
string(")");
|
string(")");
|
||||||
;
|
;
|
||||||
char cat_buff[params.size() + 1];
|
char cat_buff[params.size() + 1 + N - 1];
|
||||||
std::copy(method, method + N - 1, cat_buff);
|
std::copy(method, method + N - 1, cat_buff);
|
||||||
std::copy(params.data() + N - 1, params.data() + params.size() + 1, cat_buff + N - 1);
|
std::copy(params.data(), params.data() + params.size() + 1, cat_buff + N - 1);
|
||||||
return call<R, Args...>(vm, object, vm.make_call_handle(cat_buff), args...);
|
return call<R, Args...>(vm, object, vm.make_call_handle(cat_buff), args...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,12 +202,12 @@ namespace wren {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename... Args>
|
template <typename T, typename... Args>
|
||||||
inline T* make_wren_object(VM& vm, ModuleAndName mn, Args&&... args) {
|
inline ForeignObject<T> make_wren_object(VM& vm, ModuleAndName mn, Args&&... args) {
|
||||||
variable(vm, mn, 0);
|
variable_ensure_slot(vm, mn, 0);
|
||||||
void* const mem = vm.set_slot_new_foreign(0, 0, sizeof(T));
|
void* const mem = vm.set_slot_new_foreign(0, 0, sizeof(T));
|
||||||
try {
|
try {
|
||||||
T* const obj = new(mem) T{std::forward<Args>(args)...};
|
T* const obj = new(mem) T{std::forward<Args>(args)...};
|
||||||
return obj;
|
return {obj, vm.slot_handle(0)};
|
||||||
}
|
}
|
||||||
catch (const std::runtime_error& err) {
|
catch (const std::runtime_error& err) {
|
||||||
abort_fiber_with_error(vm, 1, err.what());
|
abort_fiber_with_error(vm, 1, err.what());
|
||||||
|
@ -233,7 +217,7 @@ namespace wren {
|
||||||
|
|
||||||
#if defined(WRENPP_WITH_NAME_GUESSING)
|
#if defined(WRENPP_WITH_NAME_GUESSING)
|
||||||
template <typename T, dhandy::bt::string Mod, typename... Args>
|
template <typename T, dhandy::bt::string Mod, typename... Args>
|
||||||
inline T* make_wren_object(VM& vm, Args&&... args) {
|
inline ForeignObject<T> make_wren_object(VM& vm, Args&&... args) {
|
||||||
return make_wren_object<T>(
|
return make_wren_object<T>(
|
||||||
vm,
|
vm,
|
||||||
MN<Mod, g_guessed_class_name<T>>,
|
MN<Mod, g_guessed_class_name<T>>,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright 2020-2022, Michele Santullo
|
/* Copyright 2020-2024, Michele Santullo
|
||||||
* This file is part of wrenpp.
|
* This file is part of wrenpp.
|
||||||
*
|
*
|
||||||
* Wrenpp is free software: you can redistribute it and/or modify
|
* Wrenpp is free software: you can redistribute it and/or modify
|
||||||
|
@ -18,6 +18,7 @@
|
||||||
#include "wrenpp/handle.hpp"
|
#include "wrenpp/handle.hpp"
|
||||||
#include "wrenpp/vm.hpp"
|
#include "wrenpp/vm.hpp"
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <ciso646>
|
||||||
|
|
||||||
namespace wren {
|
namespace wren {
|
||||||
Handle::~Handle() noexcept {
|
Handle::~Handle() noexcept {
|
||||||
|
@ -25,7 +26,12 @@ namespace wren {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Handle::release() noexcept {
|
void Handle::release() noexcept {
|
||||||
assert(m_vm);
|
assert(m_vm or not m_handle);
|
||||||
m_vm->release_handle(*this);
|
if (m_vm)
|
||||||
|
m_vm->release_handle(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Handle::set_to_slot (int slot) {
|
||||||
|
m_vm->set_slot_handle(*this, slot);
|
||||||
}
|
}
|
||||||
} //namespace wren
|
} //namespace wren
|
||||||
|
|
Loading…
Add table
Reference in a new issue