Created
October 15, 2022 13:46
-
-
Save xiaoxiao921/2d087b9134394297c219805dcce3452f to your computer and use it in GitHub Desktop.
C++ Template
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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