wrappers.h 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. /* Luwra
  2. * Minimal-overhead Lua wrapper for C++
  3. *
  4. * Copyright (C) 2015, Ole Krüger <ole@vprsm.de>
  5. */
  6. #ifndef LUWRA_WRAPPERS_H_
  7. #define LUWRA_WRAPPERS_H_
  8. #include "common.h"
  9. #include "types.h"
  10. #include "stack.h"
  11. LUWRA_NS_BEGIN
  12. namespace internal {
  13. // Function helpers
  14. template <typename T>
  15. struct FunctionWrapper {
  16. static_assert(
  17. sizeof(T) == -1,
  18. "The FunctionWrapper template expects a function signature as parameter"
  19. );
  20. };
  21. template <>
  22. struct FunctionWrapper<void()> {
  23. template <void(*funptr)()> static
  24. int invoke(State*) {
  25. funptr();
  26. return 0;
  27. }
  28. };
  29. template <typename R>
  30. struct FunctionWrapper<R()> {
  31. template <R(*funptr)()> static
  32. int invoke(State* state) {
  33. return Value<R>::push(state, funptr());
  34. }
  35. };
  36. template <typename... A>
  37. struct FunctionWrapper<void(A...)> {
  38. template <void (*funptr)(A...)> static
  39. int invoke(State* state) {
  40. apply(state, funptr);
  41. return 0;
  42. }
  43. };
  44. template <typename R, typename... A>
  45. struct FunctionWrapper<R(A...)> {
  46. template <R (*funptr)(A...)> static
  47. int invoke(State* state) {
  48. return Value<R>::push(
  49. state,
  50. apply(state, funptr)
  51. );
  52. }
  53. };
  54. // Method helpers
  55. template <typename T, typename S>
  56. struct MethodWrapper {
  57. static_assert(
  58. sizeof(T) == -1,
  59. "The MethodWrapper template expects a type name and a function signature as parameter"
  60. );
  61. };
  62. template <typename T, typename R, typename... A>
  63. struct MethodWrapper<T, R(A...)> {
  64. using MethodPointerType = R (T::*)(A...);
  65. using FunctionSignature = R (T*, A...);
  66. template <MethodPointerType MethodPointer> static
  67. R delegate(T* parent, A... args) {
  68. return (parent->*MethodPointer)(std::forward<A>(args)...);
  69. }
  70. };
  71. }
  72. /**
  73. * Assuming its parameters can be retrieved from the Lua stack, ordinary functions can be wrapped
  74. * using the `WrapFunction` instance in order to produce a C function which can be used by the
  75. * Lua VM.
  76. *
  77. * Assuming your function has the following signature:
  78. *
  79. * R my_fun(A0, A1 ... An);
  80. *
  81. * Generate a Lua-compatible like so:
  82. *
  83. * CFunction wrapped_fun = WrapFunction<R(A0, A1 ... An), my_fun>;
  84. */
  85. template <
  86. typename S,
  87. S* FunctionPointer
  88. >
  89. constexpr CFunction WrapFunction =
  90. &internal::FunctionWrapper<S>::template invoke<FunctionPointer>;
  91. /**
  92. * Works similiar to `WrapFunction`. Given a class or struct declaration as follows:
  93. *
  94. * struct T {
  95. * R my_method(A0, A1 ... An);
  96. * };
  97. *
  98. * You might wrap this method easily:
  99. *
  100. * CFunction wrapped_meth = WrapMethod<T, R(A0, A1 ... An), &T::my_method>;
  101. *
  102. * In Lua, assuming `instance` is a userdata instance of type `T`, x0, x1 ... xn are instances
  103. * of A0, A1 ... An, and the method has been bound as `my_method`; it is possible to invoke the
  104. * method like so:
  105. *
  106. * instance:my_method(x0, x1 ... xn)
  107. */
  108. template <
  109. typename T,
  110. typename S,
  111. typename internal::MethodWrapper<T, S>::MethodPointerType MethodPointer
  112. >
  113. constexpr CFunction WrapMethod =
  114. WrapFunction<
  115. internal::MethodWrapper<T, S>::FunctionSignature,
  116. internal::MethodWrapper<T, S>::template delegate<MethodPointer>
  117. >;
  118. LUWRA_NS_END
  119. #endif