| 12 | // return value (if any) onto the stack. |
| 13 | template<typename RetType, typename... Ts> |
| 14 | struct FuncInfoHolder |
| 15 | { |
| 16 | typedef RetType(*FuncType)(Ts...); |
| 17 | |
| 18 | template<FuncType funcToCall> |
| 19 | struct FuncCompiletime |
| 20 | { |
| 21 | // The function to call is embedded into call_native_function at |
| 22 | // compile-time through template magic. |
| 23 | // Performance is so similar to run-time function calls that |
| 24 | // this is not recommended due to the ugly syntax it requires. |
| 25 | static duk_ret_t call_native_function(duk_context* ctx) |
| 26 | { |
| 27 | auto bakedArgs = dukglue::detail::get_stack_values<Ts...>(ctx); |
| 28 | actually_call(ctx, bakedArgs); |
| 29 | return std::is_void<RetType>::value ? 0 : 1; |
| 30 | } |
| 31 | |
| 32 | private: |
| 33 | // this mess is to support functions with void return values |
| 34 | |
| 35 | template<typename Dummy = RetType, typename... BakedTs> |
| 36 | static typename std::enable_if<!std::is_void<Dummy>::value>::type actually_call(duk_context* ctx, const std::tuple<BakedTs...>& args) |
| 37 | { |
| 38 | // ArgStorage has some static_asserts in it that validate value types, |
| 39 | // so we typedef it to force ArgStorage<RetType> to compile and run the asserts |
| 40 | typedef typename dukglue::types::ArgStorage<RetType>::type ValidateReturnType; |
| 41 | |
| 42 | RetType return_val = dukglue::detail::apply_fp(funcToCall, args); |
| 43 | |
| 44 | using namespace dukglue::types; |
| 45 | DukType<typename Bare<RetType>::type>::template push<RetType>(ctx, std::move(return_val)); |
| 46 | } |
| 47 | |
| 48 | template<typename Dummy = RetType, typename... BakedTs> |
| 49 | static typename std::enable_if<std::is_void<Dummy>::value>::type actually_call(duk_context* ctx, const std::tuple<BakedTs...>& args) |
| 50 | { |
| 51 | dukglue::detail::apply_fp(funcToCall, args); |
| 52 | } |
| 53 | }; |
| 54 | |
| 55 | struct FuncRuntime |
| 56 | { |
| 57 | // Pull the address of the function to call from the |
| 58 | // Duktape function object at run time. |
| 59 | static duk_ret_t call_native_function(duk_context* ctx) |
| 60 | { |
| 61 | duk_push_current_function(ctx); |
| 62 | duk_get_prop_string(ctx, -1, "\xFF" "func_ptr"); |
| 63 | void* fp_void = duk_require_pointer(ctx, -1); |
| 64 | if (fp_void == NULL) { |
| 65 | duk_error(ctx, DUK_RET_TYPE_ERROR, "what even"); |
| 66 | return DUK_RET_TYPE_ERROR; |
| 67 | } |
| 68 | |
| 69 | duk_pop_2(ctx); |
| 70 | |
| 71 | static_assert(sizeof(RetType(*)(Ts...)) == sizeof(void*), "Function pointer and data pointer are different sizes"); |
nothing calls this directly
no outgoing calls
no test coverage detected