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);
|
||||
|
||||
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();
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -52,10 +52,19 @@ foreign class ClassB {
|
|||
}
|
||||
|
||||
foreign greeting_message(first_name, family_name, emoji)
|
||||
foreign set_obj_c (obj)
|
||||
foreign get_obj_c()
|
||||
}
|
||||
)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
|
||||
// non-foreign method in wren
|
||||
//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
|
||||
// do_action() on it and pass the same ClassA instance from the previous
|
||||
// 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[] = ""
|
||||
R"script(
|
||||
import "module_a" for ClassA
|
||||
import "module_b" for ClassB
|
||||
import "module_c" for ClassC
|
||||
|
||||
var obj_b = ClassB.new("TheWren")
|
||||
obj_b.do_action(ClassA.new("instanciated from script"), 2)
|
||||
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";
|
||||
|
||||
class MyWrenConfig : public wren::DefConfiguration {
|
||||
|
@ -81,6 +97,8 @@ public:
|
|||
return copied(g_module_a, sizeof(g_module_a));
|
||||
else if (module_name == "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;
|
||||
}
|
||||
|
||||
|
@ -112,6 +130,8 @@ struct ClassA {
|
|||
std::string m_message;
|
||||
};
|
||||
|
||||
class ClassC;
|
||||
|
||||
class ClassB {
|
||||
public:
|
||||
explicit ClassB (std::string nickname) : m_nickname(nickname) {
|
||||
|
@ -130,8 +150,23 @@ public:
|
|||
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:
|
||||
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
|
||||
|
||||
|
@ -149,10 +184,14 @@ int main() {
|
|||
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>)
|
||||
.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()
|
||||
.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_c", "ClassC", make_foreign_class<ClassC, std::string>)
|
||||
;
|
||||
|
||||
//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");
|
||||
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::this_thread::sleep_for(std::chrono::milliseconds(1000));
|
||||
return 0;
|
|
@ -1,4 +1,4 @@
|
|||
executable('call_cpp',
|
||||
executable('cpp_calls',
|
||||
'main.cpp',
|
||||
dependencies: wrenpp_dep,
|
||||
install: false,
|
|
@ -2,4 +2,4 @@ subdir('dieroll')
|
|||
subdir('greet')
|
||||
subdir('calendar')
|
||||
subdir('math_vector')
|
||||
subdir('call_cpp')
|
||||
subdir('cpp_calls')
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue