Add support for returning a pre-existing foreign object from a foreign method
This is potentially subject to change in the near future. This commit adds support for returning an instance (currently wrapped in ForeignObject<>) of a foreign object that is already instantiated. The object returned this way simply gets selected by handle into slot 0 of C Wren. Conversely, returning just a naked object causes wrenpp to make a Wren-accessible copy of it.
This commit is contained in:
parent
d2a1187ad5
commit
2c99251b27
13 changed files with 223 additions and 17 deletions
|
@ -128,7 +128,7 @@ int main() {
|
||||||
|
|
||||||
vm.interpret("main", g_test_script);
|
vm.interpret("main", g_test_script);
|
||||||
|
|
||||||
Calendar* const cale = std::get<0>(wren::variables<Calendar>(vm, MN<"main", "cale">));
|
Calendar* const cale = std::get<0>(wren::variables<Calendar>(vm, MN<"main", "cale">)).data();
|
||||||
cale->print_appointments();
|
cale->print_appointments();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -52,10 +52,19 @@ foreign class ClassB {
|
||||||
}
|
}
|
||||||
|
|
||||||
foreign greeting_message(first_name, family_name, emoji)
|
foreign greeting_message(first_name, family_name, emoji)
|
||||||
|
foreign set_obj_c (obj)
|
||||||
|
foreign get_obj_c()
|
||||||
}
|
}
|
||||||
)script";
|
)script";
|
||||||
|
|
||||||
//This is three examples in one:
|
constexpr char g_module_c[] =
|
||||||
|
"foreign class ClassC {" R"script(
|
||||||
|
construct new (msg) {}
|
||||||
|
foreign print_message()
|
||||||
|
}
|
||||||
|
)script";
|
||||||
|
|
||||||
|
//This is several examples in one:
|
||||||
//1. instantiate ClassA in Wren and pass it to do_action() which is a
|
//1. instantiate ClassA in Wren and pass it to do_action() which is a
|
||||||
// non-foreign method in wren
|
// non-foreign method in wren
|
||||||
//2. instantiate ClassA in C++, have C++ invoke the non-foreign method
|
//2. instantiate ClassA in C++, have C++ invoke the non-foreign method
|
||||||
|
@ -64,14 +73,21 @@ foreign class ClassB {
|
||||||
//3. instantiate ClassB in C++, have C++ invoke the non-foreign method
|
//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
|
// do_action() on it and pass the same ClassA instance from the previous
|
||||||
// step to it
|
// step to it
|
||||||
|
//4. show how to return a pre-existing instance of ClassC from ClassB both in
|
||||||
|
// C++ and Wren
|
||||||
constexpr char g_script[] = ""
|
constexpr char g_script[] = ""
|
||||||
R"script(
|
R"script(
|
||||||
import "module_a" for ClassA
|
import "module_a" for ClassA
|
||||||
import "module_b" for ClassB
|
import "module_b" for ClassB
|
||||||
|
import "module_c" for ClassC
|
||||||
|
|
||||||
var obj_b = ClassB.new("TheWren")
|
var obj_b = ClassB.new("TheWren")
|
||||||
obj_b.do_action(ClassA.new("instanciated from script"), 2)
|
obj_b.do_action(ClassA.new("instanciated from script"), 2)
|
||||||
obj_b.greeting_message("Jane", "Doe", "ʕ·͡ᴥ·ʔ")
|
obj_b.greeting_message("Jane", "Doe", "ʕ·͡ᴥ·ʔ")
|
||||||
|
|
||||||
|
var obj_c = ClassC.new("Message of ClassC object instantiated in Wren")
|
||||||
|
obj_b.set_obj_c(obj_c)
|
||||||
|
obj_b.get_obj_c().print_message()
|
||||||
)script";
|
)script";
|
||||||
|
|
||||||
class MyWrenConfig : public wren::DefConfiguration {
|
class MyWrenConfig : public wren::DefConfiguration {
|
||||||
|
@ -81,6 +97,8 @@ public:
|
||||||
return copied(g_module_a, sizeof(g_module_a));
|
return copied(g_module_a, sizeof(g_module_a));
|
||||||
else if (module_name == "module_b")
|
else if (module_name == "module_b")
|
||||||
return copied(g_module_b, sizeof(g_module_b));
|
return copied(g_module_b, sizeof(g_module_b));
|
||||||
|
else if (module_name == "module_c")
|
||||||
|
return copied(g_module_c, sizeof(g_module_c));
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,6 +130,8 @@ struct ClassA {
|
||||||
std::string m_message;
|
std::string m_message;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ClassC;
|
||||||
|
|
||||||
class ClassB {
|
class ClassB {
|
||||||
public:
|
public:
|
||||||
explicit ClassB (std::string nickname) : m_nickname(nickname) {
|
explicit ClassB (std::string nickname) : m_nickname(nickname) {
|
||||||
|
@ -130,8 +150,23 @@ public:
|
||||||
m_nickname << "' " << family_name << "\" " << emoji << '\n';
|
m_nickname << "' " << family_name << "\" " << emoji << '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_obj_c (wren::ForeignObject<ClassC> obj) {
|
||||||
|
m_obj_c = std::move(obj);
|
||||||
|
}
|
||||||
|
wren::ForeignObject<ClassC>* get_obj_c() { return &m_obj_c; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string m_nickname;
|
std::string m_nickname;
|
||||||
|
wren::ForeignObject<ClassC> m_obj_c;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ClassC {
|
||||||
|
public:
|
||||||
|
ClassC (std::string msg) : m_message(msg) {}
|
||||||
|
void print_message() const { std::cout << m_message << '\n'; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_message;
|
||||||
};
|
};
|
||||||
} //unnamed namespace
|
} //unnamed namespace
|
||||||
|
|
||||||
|
@ -149,10 +184,14 @@ int main() {
|
||||||
vm.callback_manager()
|
vm.callback_manager()
|
||||||
.add_callback(false, "module_a", "ClassA", "say_hi()", make_function_bindable<&ClassA::say_hi>)
|
.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>)
|
.add_callback(false, "module_b", "ClassB", "greeting_message(_,_,_)", make_function_bindable<&ClassB::greeting_message>)
|
||||||
|
.add_callback(false, "module_b", "ClassB", "set_obj_c(_)", make_function_bindable<&ClassB::set_obj_c>)
|
||||||
|
.add_callback(false, "module_b", "ClassB", "get_obj_c()", make_function_bindable<&ClassB::get_obj_c>)
|
||||||
|
.add_callback(false, "module_c", "ClassC", "print_message()", make_function_bindable<&ClassC::print_message>)
|
||||||
;
|
;
|
||||||
vm.class_manager()
|
vm.class_manager()
|
||||||
.add_class_maker("module_b", "ClassB", make_foreign_class<ClassB, std::string>)
|
.add_class_maker("module_b", "ClassB", make_foreign_class<ClassB, std::string>)
|
||||||
.add_class_maker("module_a", "ClassA", make_foreign_class<ClassA, std::string>)
|
.add_class_maker("module_a", "ClassA", make_foreign_class<ClassA, std::string>)
|
||||||
|
.add_class_maker("module_c", "ClassC", make_foreign_class<ClassC, std::string>)
|
||||||
;
|
;
|
||||||
|
|
||||||
//Example 1: invoke obj_b.do_action() from Wren passing an obj_a that's
|
//Example 1: invoke obj_b.do_action() from Wren passing an obj_a that's
|
||||||
|
@ -169,6 +208,11 @@ int main() {
|
||||||
auto obj_b = make_wren_object<ClassB>(vm, wren::MN<"module_b", "ClassB">, "TheCpp");
|
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);
|
wren::call<void>(vm, obj_b, "do_action", obj_a, 4);
|
||||||
|
|
||||||
|
//Example 4: set obj_c on obj_c and query it back
|
||||||
|
wren::ForeignObject<ClassC> obj_c = make_wren_object<ClassC>(vm, wren::MN<"module_c", "ClassC">, "Message of ClassC object instantiated in C++");
|
||||||
|
obj_b.object().set_obj_c(std::move(obj_c));
|
||||||
|
obj_b.object().get_obj_c()->object().print_message();
|
||||||
|
|
||||||
std::cout << "Quitting in 1 sec" << std::endl;
|
std::cout << "Quitting in 1 sec" << std::endl;
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
|
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
|
||||||
return 0;
|
return 0;
|
|
@ -1,4 +1,4 @@
|
||||||
executable('call_cpp',
|
executable('cpp_calls',
|
||||||
'main.cpp',
|
'main.cpp',
|
||||||
dependencies: wrenpp_dep,
|
dependencies: wrenpp_dep,
|
||||||
install: false,
|
install: false,
|
|
@ -2,4 +2,4 @@ subdir('dieroll')
|
||||||
subdir('greet')
|
subdir('greet')
|
||||||
subdir('calendar')
|
subdir('calendar')
|
||||||
subdir('math_vector')
|
subdir('math_vector')
|
||||||
subdir('call_cpp')
|
subdir('cpp_calls')
|
||||||
|
|
42
include/wrenpp/detail/deref_ifn.hpp
Normal file
42
include/wrenpp/detail/deref_ifn.hpp
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
/* 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 <type_traits>
|
||||||
|
|
||||||
|
namespace wren::detail {
|
||||||
|
|
||||||
|
//Dereferences the given parameter if necessary, always returning an optionally
|
||||||
|
//cv-qualified ref
|
||||||
|
template <typename T>
|
||||||
|
struct DerefIFN {
|
||||||
|
static typename std::remove_reference<T>::type& deref (
|
||||||
|
typename std::remove_reference<T>::type& param
|
||||||
|
) {
|
||||||
|
return param;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct DerefIFN<T*> {
|
||||||
|
static T& deref (T* param) { return *param; }
|
||||||
|
};
|
||||||
|
|
||||||
|
//Add specialisations for std::unique_ptr & co?
|
||||||
|
|
||||||
|
} //namespace wren::detail
|
|
@ -22,6 +22,30 @@
|
||||||
|
|
||||||
namespace wren {
|
namespace wren {
|
||||||
|
|
||||||
|
class VM;
|
||||||
|
|
||||||
|
//This is meant to be a short lived object representing a still-in-a-slot
|
||||||
|
//foreign object. Upon casting it to ForeignObject it will create a handle to
|
||||||
|
//the data in given slot
|
||||||
|
template <typename T>
|
||||||
|
class TempForeignObject {
|
||||||
|
public:
|
||||||
|
TempForeignObject (VM* vm, T* object, int slot_num) :
|
||||||
|
m_vm(vm),
|
||||||
|
m_data(object),
|
||||||
|
m_slot_num(slot_num)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
VM* vm() const { return m_vm; }
|
||||||
|
T* data() const { return m_data; }
|
||||||
|
int slot_num() const { return m_slot_num; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
VM* m_vm;
|
||||||
|
T* m_data;
|
||||||
|
int m_slot_num;
|
||||||
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class ForeignObject {
|
class ForeignObject {
|
||||||
public:
|
public:
|
||||||
|
@ -29,6 +53,7 @@ public:
|
||||||
ForeignObject (std::nullptr_t) : ForeignObject() {}
|
ForeignObject (std::nullptr_t) : ForeignObject() {}
|
||||||
ForeignObject (T* obj, Handle&& handle);
|
ForeignObject (T* obj, Handle&& handle);
|
||||||
ForeignObject (ForeignObject&&) = default;
|
ForeignObject (ForeignObject&&) = default;
|
||||||
|
ForeignObject (const TempForeignObject<T>& temp_object);
|
||||||
~ForeignObject() noexcept = default;
|
~ForeignObject() noexcept = default;
|
||||||
|
|
||||||
ForeignObject& operator= (ForeignObject&&) = default;
|
ForeignObject& operator= (ForeignObject&&) = default;
|
||||||
|
@ -58,6 +83,12 @@ inline ForeignObject<T>::ForeignObject (T* obj, Handle&& handle) :
|
||||||
m_object(obj)
|
m_object(obj)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline ForeignObject<T>::ForeignObject (const TempForeignObject<T>& temp_object) :
|
||||||
|
m_handle(temp_object.vm(), temp_object.slot_num()),
|
||||||
|
m_object(temp_object.data())
|
||||||
|
{ }
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline void ForeignObject<T>::set_to_slot (int num) {
|
inline void ForeignObject<T>::set_to_slot (int num) {
|
||||||
m_handle.set_to_slot(num);
|
m_handle.set_to_slot(num);
|
||||||
|
|
41
include/wrenpp/detail/is_kindof_handle.hpp
Normal file
41
include/wrenpp/detail/is_kindof_handle.hpp
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
/* 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 "deref_ifn.hpp"
|
||||||
|
|
||||||
|
namespace wren::detail {
|
||||||
|
|
||||||
|
template <typename T, typename TRaw>
|
||||||
|
struct IsKindOfHandleHelper {
|
||||||
|
static constexpr bool value = false;
|
||||||
|
};
|
||||||
|
template <typename TRaw>
|
||||||
|
struct IsKindOfHandleHelper<Handle, TRaw> {
|
||||||
|
static constexpr bool value = true;
|
||||||
|
static void set_to_slot (int slot_num, TRaw obj) {DerefIFN<TRaw>::deref(obj).set_to_slot(slot_num);}
|
||||||
|
};
|
||||||
|
template <typename U, typename TRaw>
|
||||||
|
struct IsKindOfHandleHelper<ForeignObject<U>, TRaw> {
|
||||||
|
static constexpr bool value = true;
|
||||||
|
static void set_to_slot (int slot_num, TRaw obj) {DerefIFN<TRaw>::deref(obj).set_to_slot(slot_num);}
|
||||||
|
};
|
||||||
|
template <typename T>
|
||||||
|
using IsKindOfHandle = IsKindOfHandleHelper<typename std::remove_pointer<typename std::remove_cvref<T>::type>::type, T>;
|
||||||
|
|
||||||
|
} //namespace wren::detail
|
|
@ -19,7 +19,9 @@
|
||||||
|
|
||||||
#include "../vm.hpp"
|
#include "../vm.hpp"
|
||||||
#include "../handle.hpp"
|
#include "../handle.hpp"
|
||||||
|
#include "foreign_object.hpp"
|
||||||
#include "module_and_name.hpp"
|
#include "module_and_name.hpp"
|
||||||
|
#include "is_kindof_handle.hpp"
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
@ -34,8 +36,14 @@ namespace wren {
|
||||||
template<typename T>struct GetTypeToRetType{
|
template<typename T>struct GetTypeToRetType{
|
||||||
static_assert(not std::is_fundamental_v<T>, "User type expected");
|
static_assert(not std::is_fundamental_v<T>, "User type expected");
|
||||||
static_assert(not std::is_pointer_v<T>, "Unexpected pointer type");
|
static_assert(not std::is_pointer_v<T>, "Unexpected pointer type");
|
||||||
typedef std::remove_cv_t<T>* type;
|
typedef TempForeignObject< std::remove_cv_t<T> > type;
|
||||||
};
|
};
|
||||||
|
template<typename T>struct GetTypeToRetType<ForeignObject<T>> {
|
||||||
|
//This doesn't make much sense, essentially you're asking wrenpp to
|
||||||
|
//give you a foreign object by vm/slot when you already have its
|
||||||
|
//handle
|
||||||
|
};
|
||||||
|
template<typename T>struct GetTypeToRetType<TempForeignObject<T>> : TType<TempForeignObject<T>>{};
|
||||||
template<>struct GetTypeToRetType<const char*> : TType<const char*>{};
|
template<>struct GetTypeToRetType<const char*> : TType<const char*>{};
|
||||||
template<>struct GetTypeToRetType<double> : TType<double>{};
|
template<>struct GetTypeToRetType<double> : TType<double>{};
|
||||||
template<>struct GetTypeToRetType<bool> : TType<bool>{};
|
template<>struct GetTypeToRetType<bool> : TType<bool>{};
|
||||||
|
@ -166,7 +174,7 @@ namespace wren {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline detail::GetTypeToRetType_t<T> get (VM& vm, int slot_num) {
|
inline detail::GetTypeToRetType_t<T> get (VM& vm, int slot_num) {
|
||||||
return foreign<T>(vm, slot_num);
|
return {&vm, foreign<T>(vm, slot_num), slot_num};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<> const char* get<const char*> (VM& vm, int slot_num);
|
template<> const char* get<const char*> (VM& vm, int slot_num);
|
||||||
|
|
|
@ -27,6 +27,7 @@ namespace wren {
|
||||||
Handle() noexcept;
|
Handle() noexcept;
|
||||||
Handle (const Handle&) = delete;
|
Handle (const Handle&) = delete;
|
||||||
Handle (Handle&& other) noexcept;
|
Handle (Handle&& other) noexcept;
|
||||||
|
Handle (VM* vm, int slot_num);
|
||||||
Handle (VM* vm, WrenHandle* handle) noexcept :
|
Handle (VM* vm, WrenHandle* handle) noexcept :
|
||||||
m_handle(handle),
|
m_handle(handle),
|
||||||
m_vm(vm)
|
m_vm(vm)
|
||||||
|
|
|
@ -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/is_kindof_handle.hpp"
|
||||||
#include "detail/foreign_object.hpp"
|
#include "detail/foreign_object.hpp"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
@ -62,6 +63,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>
|
||||||
|
struct CleanParamForGet { typedef typename std::decay<T>::type type; };
|
||||||
|
template <typename T>
|
||||||
|
struct CleanParamForGet<ForeignObject<T>> { typedef T type; };
|
||||||
|
template <typename T>
|
||||||
|
using CleanParamForGetT = typename CleanParamForGet<T>::type;
|
||||||
|
|
||||||
//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
|
||||||
|
@ -82,8 +90,8 @@ namespace wren {
|
||||||
template <int... Indices>
|
template <int... Indices>
|
||||||
static R call_implem (std::integer_sequence<int, Indices...>, VM& vm) {
|
static R call_implem (std::integer_sequence<int, Indices...>, VM& vm) {
|
||||||
static_assert(sizeof...(Indices) == sizeof...(Args), "Mismatching argument count");
|
static_assert(sizeof...(Indices) == sizeof...(Args), "Mismatching argument count");
|
||||||
T* obj = foreign<T>(vm, 0);
|
T* const obj = foreign<T>(vm, 0);
|
||||||
return (obj->*Method)(get<std::decay_t<Args>>(vm, Indices + 1)...);
|
return (obj->*Method)(get<CleanParamForGetT<Args>>(vm, Indices + 1)...);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
template <typename T, typename R, typename... Args, R(T::*ConstMethod)(Args...)const>
|
template <typename T, typename R, typename... Args, R(T::*ConstMethod)(Args...)const>
|
||||||
|
@ -95,8 +103,8 @@ namespace wren {
|
||||||
template <int... Indices>
|
template <int... Indices>
|
||||||
static R call_implem (std::integer_sequence<int, Indices...>, VM& vm) {
|
static R call_implem (std::integer_sequence<int, Indices...>, VM& vm) {
|
||||||
static_assert(sizeof...(Indices) == sizeof...(Args), "Mismatching argument count");
|
static_assert(sizeof...(Indices) == sizeof...(Args), "Mismatching argument count");
|
||||||
T* obj = foreign<T>(vm, 0);
|
T* const obj = foreign<T>(vm, 0);
|
||||||
return (obj->*ConstMethod)(get<std::decay_t<Args>>(vm, Indices + 1)...);
|
return (obj->*ConstMethod)(get<CleanParamForGetT<Args>>(vm, Indices + 1)...);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
template <typename R, typename... Args, R(*Function)(Args...)>
|
template <typename R, typename... Args, R(*Function)(Args...)>
|
||||||
|
@ -108,7 +116,7 @@ namespace wren {
|
||||||
template <int... Indices>
|
template <int... Indices>
|
||||||
static R call_implem (std::integer_sequence<int, Indices...>, VM& vm) {
|
static R call_implem (std::integer_sequence<int, Indices...>, VM& vm) {
|
||||||
static_assert(sizeof...(Indices) == sizeof...(Args), "Mismatching argument count");
|
static_assert(sizeof...(Indices) == sizeof...(Args), "Mismatching argument count");
|
||||||
return (*Function)(get<std::decay_t<Args>>(vm, Indices + 1)...);
|
return (*Function)(get<CleanParamForGetT<Args>>(vm, Indices + 1)...);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -125,10 +133,14 @@ namespace wren {
|
||||||
else {
|
else {
|
||||||
auto ret = CallImplemProvider<V>::call_implem(std::make_integer_sequence<int, argument_count>(), vm);
|
auto ret = CallImplemProvider<V>::call_implem(std::make_integer_sequence<int, argument_count>(), vm);
|
||||||
//TODO: check for errors
|
//TODO: check for errors
|
||||||
vm.ensure_slots(1);
|
assert(vm.slot_count() >= 1); //vm.ensure_slots(1);
|
||||||
if constexpr (std::is_fundamental<R>::value) {
|
if constexpr (std::is_fundamental<R>::value) {
|
||||||
set(vm, 0, ret);
|
set(vm, 0, ret);
|
||||||
}
|
}
|
||||||
|
else if constexpr (IsKindOfHandle<R>::value) {
|
||||||
|
IsKindOfHandle<R>::set_to_slot(0, ret);
|
||||||
|
assert(vm.slot_type(0) == SlotType::Foreign);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
ModuleAndName wren_name = wren_class_name_from_type<R>(vm);
|
ModuleAndName wren_name = wren_class_name_from_type<R>(vm);
|
||||||
ForeignObject<R> 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));
|
||||||
|
|
|
@ -21,6 +21,11 @@
|
||||||
#include <ciso646>
|
#include <ciso646>
|
||||||
|
|
||||||
namespace wren {
|
namespace wren {
|
||||||
|
Handle::Handle (VM* vm, int slot_num) :
|
||||||
|
Handle(vm->slot_handle(slot_num))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
Handle::~Handle() noexcept {
|
Handle::~Handle() noexcept {
|
||||||
release();
|
release();
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ wrenpp = library(meson.project_name(),
|
||||||
'class_manager.cpp',
|
'class_manager.cpp',
|
||||||
'wren_class_name_from_type.cpp',
|
'wren_class_name_from_type.cpp',
|
||||||
'module_and_name.cpp',
|
'module_and_name.cpp',
|
||||||
|
'setters_getters.cpp',
|
||||||
dependencies: [wren_dep, crc32_dep],
|
dependencies: [wren_dep, crc32_dep],
|
||||||
include_directories: public_incl,
|
include_directories: public_incl,
|
||||||
install: (not meson.is_subproject() or get_option('default_library')=='shared'),
|
install: (not meson.is_subproject() or get_option('default_library')=='shared'),
|
||||||
|
|
21
src/setters_getters.cpp
Normal file
21
src/setters_getters.cpp
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
/* 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/detail/setters_getters.hpp"
|
||||||
|
|
||||||
|
namespace wren {
|
||||||
|
} //namespace wren
|
Loading…
Reference in a new issue