functions.hpp 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. /* Luwra
  2. * Minimal-overhead Lua wrapper for C++
  3. *
  4. * Copyright (C) 2015, Ole Krüger <ole@vprsm.de>
  5. */
  6. #ifndef LUWRA_FUNCTIONS_H_
  7. #define LUWRA_FUNCTIONS_H_
  8. #include "common.hpp"
  9. #include "types.hpp"
  10. #include "stack.hpp"
  11. LUWRA_NS_BEGIN
  12. namespace internal {
  13. template <typename T>
  14. struct FunctionWrapper {
  15. static_assert(
  16. sizeof(T) == -1,
  17. "Parameter to FunctionWrapper is not a function signature"
  18. );
  19. };
  20. template <>
  21. struct FunctionWrapper<void()> {
  22. template <void(*function_pointer)()> static inline
  23. int invoke(State*) {
  24. function_pointer();
  25. return 0;
  26. }
  27. };
  28. template <typename R>
  29. struct FunctionWrapper<R()> {
  30. template <R(*function_pointer)()> static inline
  31. int invoke(State* state) {
  32. return push(state, function_pointer());
  33. }
  34. };
  35. template <typename... A>
  36. struct FunctionWrapper<void(A...)> {
  37. template <void (*function_pointer)(A...)> static inline
  38. int invoke(State* state) {
  39. apply(state, function_pointer);
  40. return 0;
  41. }
  42. };
  43. template <typename R, typename... A>
  44. struct FunctionWrapper<R(A...)> {
  45. template <R (*function_pointer)(A...)> static inline
  46. int invoke(State* state) {
  47. return push(
  48. state,
  49. apply(state, function_pointer)
  50. );
  51. }
  52. };
  53. template <typename T>
  54. struct FunctionWrapperHelper {
  55. static_assert(
  56. sizeof(T) == -1,
  57. "Parameter to FunctionWrapperHelper is not a function pointer"
  58. );
  59. };
  60. template <typename R, typename... A>
  61. struct FunctionWrapperHelper<R(*)(A...)> {
  62. using Signature = R(A...);
  63. };
  64. }
  65. /**
  66. * Assuming its parameters can be retrieved from the Lua stack, ordinary functions can be wrapped
  67. * using the `wrap_function` instance in order to produce a C function which can be used by the
  68. * Lua VM.
  69. *
  70. * Assuming your function has the following signature:
  71. *
  72. * R my_fun(A0, A1 ... An);
  73. *
  74. * Generate a Lua-compatible like so:
  75. *
  76. * CFunction wrapped_fun = wrap_function<R(A0, A1 ... An), my_fun>;
  77. */
  78. template <
  79. typename S,
  80. S* function_pointer
  81. >
  82. constexpr CFunction wrap_function =
  83. &internal::FunctionWrapper<S>::template invoke<function_pointer>;
  84. /**
  85. * This macros allows you to wrap functions without providing a type signature.
  86. */
  87. #define LUWRA_WRAP_FUNCTION(fun) \
  88. (luwra::wrap_function< \
  89. typename luwra::internal::FunctionWrapperHelper<decltype(&fun)>::Signature, \
  90. &fun \
  91. >)
  92. LUWRA_NS_END
  93. #endif