| 68 | |
| 69 | |
| 70 | struct MethodRuntime |
| 71 | { |
| 72 | static duk_ret_t finalize_method(duk_context* ctx) |
| 73 | { |
| 74 | // clean up the MethodHolder reference |
| 75 | duk_get_prop_string(ctx, 0, "\xFF" "method_holder"); |
| 76 | |
| 77 | void* method_holder_void = duk_require_pointer(ctx, -1); |
| 78 | MethodHolder* method_holder = static_cast<MethodHolder*>(method_holder_void); |
| 79 | delete method_holder; |
| 80 | |
| 81 | return 0; |
| 82 | } |
| 83 | |
| 84 | static duk_ret_t call_native_method(duk_context* ctx) |
| 85 | { |
| 86 | // get this.obj_ptr |
| 87 | duk_push_this(ctx); |
| 88 | duk_get_prop_string(ctx, -1, "\xFF" "obj_ptr"); |
| 89 | void* obj_void = duk_get_pointer(ctx, -1); |
| 90 | if (obj_void == nullptr) { |
| 91 | duk_error(ctx, DUK_RET_REFERENCE_ERROR, "Invalid native object for 'this'"); |
| 92 | return DUK_RET_REFERENCE_ERROR; |
| 93 | } |
| 94 | |
| 95 | duk_pop_2(ctx); // pop this.obj_ptr and this |
| 96 | |
| 97 | // get current_function.method_info |
| 98 | duk_push_current_function(ctx); |
| 99 | duk_get_prop_string(ctx, -1, "\xFF" "method_holder"); |
| 100 | void* method_holder_void = duk_require_pointer(ctx, -1); |
| 101 | if (method_holder_void == nullptr) { |
| 102 | duk_error(ctx, DUK_RET_TYPE_ERROR, "Method pointer missing?!"); |
| 103 | return DUK_RET_TYPE_ERROR; |
| 104 | } |
| 105 | |
| 106 | duk_pop_2(ctx); |
| 107 | |
| 108 | // (should always be valid unless someone is intentionally messing with this.obj_ptr...) |
| 109 | Cls* obj = static_cast<Cls*>(obj_void); |
| 110 | MethodHolder* method_holder = static_cast<MethodHolder*>(method_holder_void); |
| 111 | |
| 112 | // read arguments and call method |
| 113 | auto bakedArgs = dukglue::detail::get_stack_values<Ts...>(ctx); |
| 114 | actually_call(ctx, method_holder->method, obj, bakedArgs); |
| 115 | return std::is_void<RetType>::value ? 0 : 1; |
| 116 | } |
| 117 | |
| 118 | // this mess is to support functions with void return values |
| 119 | template<typename Dummy = RetType, typename... BakedTs> |
| 120 | static typename std::enable_if<!std::is_void<Dummy>::value>::type actually_call(duk_context* ctx, MethodType method, Cls* obj, const std::tuple<BakedTs...>& args) |
| 121 | { |
| 122 | // ArgStorage has some static_asserts in it that validate value types, |
| 123 | // so we typedef it to force ArgStorage<RetType> to compile and run the asserts |
| 124 | typedef typename dukglue::types::ArgStorage<RetType>::type ValidateReturnType; |
| 125 | |
| 126 | RetType return_val = dukglue::detail::apply_method<Cls, RetType, Ts...>(method, obj, args); |
| 127 |
nothing calls this directly
no outgoing calls
no test coverage detected