Allow client code to provide their foreign_class_fn() implementation.

This commit is contained in:
King_DuckZ 2020-04-26 21:25:26 +02:00
parent 2c2d783730
commit 3d68124a60
2 changed files with 27 additions and 0 deletions

View file

@ -55,6 +55,19 @@ namespace wren {
auto retval = reinterpret_cast<WrenForeignMethodFn>(dfm->make(cb->owner, func)); auto retval = reinterpret_cast<WrenForeignMethodFn>(dfm->make(cb->owner, func));
return retval; return retval;
} }
WrenForeignClassMethods foreign_class_fn (WrenVM* wvm, const char* module, const char* class_name) {
auto cb = static_cast<detail::Callbacks*>(wrenGetUserData(wvm));
assert(cb);
assert(cb->foreign_class_fn and cb->config_obj and cb->owner);
foreign_class_t funcs = cb->foreign_class_fn(*cb->config_obj, cb->owner, module, class_name);
DynafuncMaker* const dfm = cb->dynafunc;
assert(dfm);
WrenForeignClassMethods retval;
retval.allocate = reinterpret_cast<WrenForeignMethodFn>(dfm->make(cb->owner, funcs.allocate));
retval.finalize = funcs.finalize;
return retval;
}
} //unnamed namespace } //unnamed namespace
struct VM::LocalData { struct VM::LocalData {
@ -106,6 +119,9 @@ namespace wren {
if (cb.foreign_method_fn) if (cb.foreign_method_fn)
wconf.bindForeignMethodFn = &foreign_method_fn; wconf.bindForeignMethodFn = &foreign_method_fn;
if (cb.foreign_class_fn)
wconf.bindForeignClassFn = &foreign_class_fn;
m_local->wvm = wrenNewVM(&wconf); m_local->wvm = wrenNewVM(&wconf);
if (not m_local->wvm) if (not m_local->wvm)
throw std::runtime_error("Failed to initialize Wren VM"); throw std::runtime_error("Failed to initialize Wren VM");

View file

@ -11,6 +11,12 @@ namespace wren {
class DynafuncMaker; class DynafuncMaker;
typedef void(*foreign_method_t)(VM*); typedef void(*foreign_method_t)(VM*);
typedef void(*finalizer_t)(void*);
struct foreign_class_t {
foreign_method_t allocate;
finalizer_t finalize;
};
namespace detail { namespace detail {
struct Callbacks { struct Callbacks {
@ -20,6 +26,7 @@ namespace wren {
const char* (*resolve_module_fn)(Configuration&, VM*, const char*, const char*) {nullptr}; const char* (*resolve_module_fn)(Configuration&, VM*, const char*, const char*) {nullptr};
char* (*load_module_fn)(Configuration&, VM*, const char*) {nullptr}; char* (*load_module_fn)(Configuration&, VM*, const char*) {nullptr};
foreign_method_t (*foreign_method_fn)(Configuration&, VM*, const char*, const char*, bool, const char*); foreign_method_t (*foreign_method_fn)(Configuration&, VM*, const char*, const char*, bool, const char*);
foreign_class_t (*foreign_class_fn)(Configuration&, VM*, const char*, const char*);
Configuration* config_obj {nullptr}; Configuration* config_obj {nullptr};
VM* owner {nullptr}; VM* owner {nullptr};
@ -57,6 +64,7 @@ namespace wren {
define_method_info(resolve_module_fn, resolve_module, const char*, const char*, const char*); define_method_info(resolve_module_fn, resolve_module, const char*, const char*, const char*);
define_method_info(load_module_fn, load_module, char*, VM*, const char*); define_method_info(load_module_fn, load_module, char*, VM*, const char*);
define_method_info(foreign_method_fn, foreign_method, foreign_method_t, VM*, const char*, const char*, bool, const char*); define_method_info(foreign_method_fn, foreign_method, foreign_method_t, VM*, const char*, const char*, bool, const char*);
define_method_info(foreign_class_fn, foreign_class, foreign_class_t, VM*, const char*, const char*);
template <typename T, typename F> struct AnyFunctionWrap; template <typename T, typename F> struct AnyFunctionWrap;
template <typename T, typename R, typename... Args> template <typename T, typename R, typename... Args>
@ -103,6 +111,9 @@ namespace wren {
if constexpr (detail::method_foreign_method::exists<T>::value) if constexpr (detail::method_foreign_method::exists<T>::value)
ret.foreign_method_fn = &detail::AnyFunctionWrap<T, decltype(&T::foreign_method_fn)>::template call<&T::foreign_method_fn>; ret.foreign_method_fn = &detail::AnyFunctionWrap<T, decltype(&T::foreign_method_fn)>::template call<&T::foreign_method_fn>;
if constexpr (detail::method_foreign_class::exists<T>::value)
ret.foreign_class_fn = &detail::AnyFunctionWrap<T, decltype(&T::foreign_class_fn)>::template call<&T::foreign_class_fn>;
return ret; return ret;
} }