Skip to content

Instantly share code, notes, and snippets.

@xiaoxiao921
Created October 15, 2022 13:46
Show Gist options
  • Save xiaoxiao921/2d087b9134394297c219805dcce3452f to your computer and use it in GitHub Desktop.
Save xiaoxiao921/2d087b9134394297c219805dcce3452f to your computer and use it in GitHub Desktop.
C++ Template
#define WREN_ADD_FOREIGN_FUNC(fn) wren_add_foreign_func<&fn>(#fn)
static std::unordered_map<void*, void(*)()> native_func_to_wren_handler;
template <typename Signature, Signature signature>
struct wren_foreign_func;
template <typename ReturnType, typename... Args, ReturnType(*function_pointer)(Args...)>
struct wren_foreign_func<ReturnType(*)(Args...), function_pointer>
{
static constexpr size_t values_count = sizeof... (Args);
static inline std::tuple<Args...> values;
struct empty {};
static inline std::conditional_t<std::is_same_v<ReturnType, void>, empty, ReturnType> return_value;
template <typename if_bool_need_to_handle_out_params, typename Head, typename... Rest>
static void handle_call_from_wren_vm()
{
constexpr int slot_index = (int)(values_count - sizeof... (Rest));
constexpr size_t tuple_index = ((size_t)slot_index) - 1;
if constexpr (std::is_arithmetic_v<Head>)
{
// this branch can be removed if we were using the actual bool type instead of just a typedef to int (BOOL)
std::get<tuple_index>(values) = wrenGetSlotType(g_wren_manager->m_vm, slot_index) == WREN_TYPE_BOOL ?
(bool)wrenGetSlotBool(g_wren_manager->m_vm, slot_index) :
(Head)wrenGetSlotDouble(g_wren_manager->m_vm, slot_index)
}
else if constexpr (std::is_same_v<Head, const char*>)
{
std::get<tuple_index>(values) = wrenGetSlotString(g_wren_manager->m_vm, slot_index);
}
else if constexpr (std::is_pointer_v<Head>)
{
std::remove_pointer_t<Head> val{};
std::get<tuple_index>(values) = &val;
if constexpr (sizeof... (Rest))
{
handle_call_from_wren_vm<bool, Rest...>();
}
else
{
if constexpr (std::is_same_v<ReturnType, void>)
{
std::apply(function_pointer, values);
handle_out_params(values);
}
else
{
return_value = std::apply(function_pointer, values);
handle_out_params(values);
}
}
return;
}
if constexpr (sizeof... (Rest))
{
handle_call_from_wren_vm<if_bool_need_to_handle_out_params, Rest...>();
}
else
{
if constexpr (std::is_same_v<ReturnType, void>)
{
std::apply(function_pointer, values);
if constexpr (std::is_same_v<if_bool_need_to_handle_out_params, bool>)
{
handle_out_params(values);
}
}
else
{
return_value = std::apply(function_pointer, values);
if constexpr (std::is_same_v<if_bool_need_to_handle_out_params, bool>)
{
handle_out_params(values);
}
else
{
if constexpr (std::is_same_v<ReturnType, void>)
{
if constexpr (std::is_arithmetic_v<ReturnType>)
{
}
else if constexpr (std::is_same_v<ReturnType, const char*>)
{
}
}
}
}
}
}
static inline list_element_count = 0;
template <size_t I = 0, typename... Rest>
static void handle_out_params(std::tuple<Rest...> tuple)
{
constexpr int list_slot = 0;
constexpr int temp_element_slot = 1;
if constexpr (I == 0)
{
wrenEnsureSlots(g_wren_manager->m_vm, sizeof...(Rest));
wrenSetSlotNewList(vm, list_slot);
if constexpr (!std::is_same_v<ReturnType, void>)
{
if constexpr (std::is_arithmetic_v<ReturnType>)
{
}
else if constexpr (std::is_same_v<ReturnType, const char*>)
{
wrenSetSlotString(g_wren_manager->m_vm, temp_element_slot, return_value);
}
wrenInsertInList(g_wren_manager->m_vm, list_slot, list_element_count++, temp_element_slot);
}
}
if constexpr (I < sizeof...(Rest))
{
const auto param = std::get<I>(tuple);
// if its an out param
if constexpr (std::is_pointer_v<std::remove_reference_t<decltype(param)>> &&
// const char* params are not out param here
!std::is_same_v<std::remove_reference_t<decltype(param)>, const char*>)
{
// todo add arg to return list
}
handle_out_params<I + 1>(tuple);
}
}
static void call()
{
handle_call_from_wren_vm<void, Args...>();
}
};
template <auto function_pointer>
void wren_add_foreign_func(std::string name)
{
native_func_to_wren_handler.insert({ function_pointer, wren_foreign_func<decltype(function_pointer), function_pointer>::call });
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment