CommonLibSSE (Parapets fork)
Loading...
Searching...
No Matches
NativeFunction.h
Go to the documentation of this file.
1#pragma once
2
6#include "RE/P/PackUnpack.h"
7#include "RE/S/Stack.h"
8#include "RE/S/StackFrame.h"
9#include "RE/T/TypeTraits.h"
10#include "RE/V/Variable.h"
11#include "RE/V/VirtualMachine.h"
12
13namespace RE
14{
15 namespace BSScript
16 {
17 namespace Impl
18 {
19 template <class F, class Tuple, std::size_t... I, class... Args>
20 inline constexpr decltype(auto) CallbackImpl(F&& a_func, Tuple&& a_tuple, std::index_sequence<I...>, Args&&... a_args)
21 {
22 return std::invoke(
23 std::forward<F>(a_func),
24 std::forward<Args>(a_args)...,
25 std::get<I>(std::forward<Tuple>(a_tuple))...);
26 }
27
28 template <class F, class Tuple, class... Args>
29 inline constexpr decltype(auto) CallBack(F&& a_func, Tuple&& a_tuple, Args&&... a_args)
30 {
31 return CallbackImpl(
32 std::forward<F>(a_func),
33 std::forward<Tuple>(a_tuple),
35 std::forward<Args>(a_args)...);
36 }
37
38 template <class... Args, std::size_t... I>
39 std::tuple<Args...> MakeTupleImpl(const StackFrame& a_frame, std::uint32_t a_page, std::index_sequence<I...>)
40 {
41 return std::forward_as_tuple(
42 a_frame.GetStackFrameVariable(I, a_page).Unpack<Args>()...);
43 }
44
45 // tuple element construction order isn't guaranteed, so we need to wrap it
46 template <class... Args>
47 std::tuple<Args...> MakeTuple(const StackFrame& a_frame, std::uint32_t a_page)
48 {
49 return MakeTupleImpl<Args...>(a_frame, a_page, std::index_sequence_for<Args...>{});
50 }
51 }
52
53 template <bool IS_LONG, class F, class R, class Base, class... Args>
55 {
56 public:
57 using result_type = R;
58 using base_type = Base;
59 using function_type = F;
60
61 NativeFunction() = delete;
64
65 NativeFunction(std::string_view a_fnName, std::string_view a_className, function_type a_callback) :
66 NF_util::NativeFunctionBase(a_fnName, a_className, is_static_base_v<base_type>, sizeof...(Args)),
67 _stub(a_callback)
68 {
69 std::size_t i = 0;
70 ((_descTable.entries[i++].second.SetType(GetRawType<Args>())), ...);
71 _retType = GetRawType<result_type>();
72 }
73
74 ~NativeFunction() override = default; // 00
75
76 bool HasStub() const override // 15
77 {
78 return static_cast<bool>(_stub);
79 }
80
81 bool MarshallAndDispatch(Variable& a_baseValue, [[maybe_unused]] Internal::VirtualMachine& a_vm, [[maybe_unused]] VMStackID a_stackID, Variable& a_resultValue, const StackFrame& a_frame) const override // 16
82 {
83 base_type base{};
84 if constexpr (std::negation_v<is_static_base<base_type>>) {
85 base = a_baseValue.Unpack<base_type>();
86 if (!base) {
87 return false;
88 }
89 }
90
91 auto page = a_frame.GetPageForFrame();
92 auto args = Impl::MakeTuple<Args...>(a_frame, page);
93 if constexpr (std::is_void_v<result_type>) {
94 if constexpr (IS_LONG) {
95 Impl::CallBack(_stub, std::move(args), std::addressof(a_vm), a_stackID, std::move(base));
96 a_resultValue.SetNone();
97 } else {
98 Impl::CallBack(_stub, std::move(args), std::move(base));
99 a_resultValue.SetNone();
100 }
101 } else {
102 if constexpr (IS_LONG) {
103 auto result = Impl::CallBack(_stub, std::move(args), std::addressof(a_vm), a_stackID, std::move(base));
104 a_resultValue.Pack<result_type>(std::move(result));
105 } else {
106 auto result = Impl::CallBack(_stub, std::move(args), std::move(base));
107 a_resultValue.Pack<result_type>(std::move(result));
108 }
109 }
110
111 return true;
112 }
113
114 protected:
115 // members
116 std::function<function_type> _stub; // 50
117 };
118 }
119
120 template <class F, class = void>
122
123 template <class R, class Cls, class... Args>
124 class NativeFunction<R(Cls, Args...), std::enable_if_t<BSScript::is_valid_short_sig_v<R, Cls, Args...>>> :
125 public BSScript::NativeFunction<false, R(Cls, Args...), R, Cls, Args...>
126 {
127 private:
128 using super = BSScript::NativeFunction<false, R(Cls, Args...), R, Cls, Args...>;
129
130 public:
132 using base_type = typename super::base_type;
134
135 using super::super;
136 };
137
138 template <class Int, class R, class Cls, class... Args>
139 class NativeFunction<R(BSScript::Internal::VirtualMachine*, Int, Cls, Args...), std::enable_if_t<BSScript::is_valid_long_sig_v<Int, R, Cls, Args...>>> :
140 public BSScript::NativeFunction<true, R(BSScript::Internal::VirtualMachine*, Int, Cls, Args...), R, Cls, Args...>
141 {
142 private:
143 using super = BSScript::NativeFunction<true, R(BSScript::Internal::VirtualMachine*, Int, Cls, Args...), R, Cls, Args...>;
144
145 public:
147 using base_type = typename super::base_type;
149
150 using super::super;
151 };
152
153 template <class Int, class R, class Cls, class... Args>
154 class NativeFunction<R(BSScript::IVirtualMachine*, Int, Cls, Args...), std::enable_if_t<BSScript::is_valid_long_sig_v<Int, R, Cls, Args...>>> :
155 public BSScript::NativeFunction<true, R(BSScript::IVirtualMachine*, Int, Cls, Args...), R, Cls, Args...>
156 {
157 private:
158 using super = BSScript::NativeFunction<true, R(BSScript::IVirtualMachine*, Int, Cls, Args...), R, Cls, Args...>;
159
160 public:
162 using base_type = typename super::base_type;
164
165 using super::super;
166 };
167
168 template <class F>
169 NativeFunction(std::string_view, std::string_view, F) -> NativeFunction<std::remove_pointer_t<F>>;
170
171 namespace BSScript
172 {
173 template <class F>
174 void IVirtualMachine::RegisterFunction(std::string_view a_fnName, std::string_view a_className, F a_callback, bool a_callableFromTasklets)
175 {
176 BindNativeMethod(new RE::NativeFunction(a_fnName, a_className, a_callback));
177 if (a_callableFromTasklets) {
178 SetCallableFromTasklets(a_className.data(), a_fnName.data(), a_callableFromTasklets);
179 }
180 }
181 }
182}
Definition: IVirtualMachine.h:39
void SetCallableFromTasklets(const char *a_className, const char *a_stateName, const char *a_fnName, bool a_callable)
void RegisterFunction(std::string_view a_fnName, std::string_view a_className, F a_callback, bool a_callableFromTasklets=false)
Definition: NativeFunction.h:174
virtual bool BindNativeMethod(IFunction *a_fn)=0
Definition: VirtualMachine.h:46
Definition: NativeFunctionBase.h:23
TypeInfo _retType
Definition: NativeFunctionBase.h:62
Internal::VDescTable _descTable
Definition: NativeFunctionBase.h:63
Definition: NativeFunction.h:55
NativeFunction(NativeFunction &&)=delete
std::function< function_type > _stub
Definition: NativeFunction.h:116
Base base_type
Definition: NativeFunction.h:58
NativeFunction(const NativeFunction &)=delete
~NativeFunction() override=default
bool MarshallAndDispatch(Variable &a_baseValue, Internal::VirtualMachine &a_vm, VMStackID a_stackID, Variable &a_resultValue, const StackFrame &a_frame) const override
Definition: NativeFunction.h:81
R result_type
Definition: NativeFunction.h:57
bool HasStub() const override
Definition: NativeFunction.h:76
F function_type
Definition: NativeFunction.h:59
NativeFunction(std::string_view a_fnName, std::string_view a_className, function_type a_callback)
Definition: NativeFunction.h:65
Definition: StackFrame.h:15
Variable & GetStackFrameVariable(std::uint32_t a_index, std::uint32_t a_pageHint) const
Definition: Variable.h:15
T Unpack() const
Definition: PackUnpack.h:298
Definition: NativeFunction.h:121
std::tuple< Args... > MakeTupleImpl(const StackFrame &a_frame, std::uint32_t a_page, std::index_sequence< I... >)
Definition: NativeFunction.h:39
std::tuple< Args... > MakeTuple(const StackFrame &a_frame, std::uint32_t a_page)
Definition: NativeFunction.h:47
constexpr decltype(auto) CallBack(F &&a_func, Tuple &&a_tuple, Args &&... a_args)
Definition: NativeFunction.h:29
constexpr decltype(auto) CallbackImpl(F &&a_func, Tuple &&a_tuple, std::index_sequence< I... >, Args &&... a_args)
Definition: NativeFunction.h:20
constexpr bool is_static_base_v
Definition: TypeTraits.h:139
Definition: AbsorbEffect.h:6
std::uint32_t VMStackID
Definition: BSCoreTypes.h:8
Definition: NiBinaryStream.h:94
SimpleArray< BSTTuple< BSFixedString, TypeInfo > > entries
Definition: VDescTable.h:24
Definition: CommonTypeTraits.h:191