CommonLibSSE (Parapets fork)
NativeFunction.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include "RE/B/BSTSmartPointer.h"
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 
13 namespace 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;
62  NativeFunction(const 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:
131  using result_type = typename super::result_type;
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:
146  using result_type = typename super::result_type;
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:
161  using result_type = typename super::result_type;
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
R result_type
Definition: NativeFunction.h:57
bool HasStub() const override
Definition: NativeFunction.h:76
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
Definition: NativeFunction.h:81
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::invoke_result_t< F, Args... > invoke(F &&a_func, Args &&... a_args) noexcept(std::is_nothrow_invocable_v< F, Args... >) requires(std
Definition: Relocation.h:201
std::tuple< Args... > MakeTupleImpl(const StackFrame &a_frame, std::uint32_t a_page, std::index_sequence< I... >)
Definition: NativeFunction.h:39
constexpr decltype(auto) CallBack(F &&a_func, Tuple &&a_tuple, Args &&... a_args)
Definition: NativeFunction.h:29
std::tuple< Args... > MakeTuple(const StackFrame &a_frame, std::uint32_t a_page)
Definition: NativeFunction.h:47
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
NativeFunction(std::string_view, std::string_view, F) -> NativeFunction< std::remove_pointer_t< F >>
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
Definition: TypeTraits.h:136