Nui
functions.hpp
Go to the documentation of this file.
1 // Copyright (c) 2017 Damien Buhl alias daminetreg (damien.buhl@lecbna.org)
2 // https://github.com/daminetreg/js-bind
3 
4 #ifndef JS_BIND_HPP
5 #define JS_BIND_HPP
6 
7 #include <utility>
8 #include <functional>
9 
10 #include <emscripten/bind.h>
11 #include <emscripten/val.h>
12 
13 #include <boost/preprocessor/repetition/repeat.hpp>
14 #include <boost/preprocessor/punctuation/comma_if.hpp>
15 #include <boost/preprocessor/stringize.hpp>
16 
17 #include <pre/type_traits/function_traits.hpp>
18 
19 #ifndef JS_BIND_MAX_ARITY
25 # define JS_BIND_MAX_ARITY 16
26 #endif
27 
28 #define JS_BIND_DETAIL_ARGS_EACH(z, n, unused) BOOST_PP_COMMA_IF(n) emscripten::val
29 
30 #define JS_BIND_DETAIL_ARGS(COUNT) BOOST_PP_REPEAT(COUNT, JS_BIND_DETAIL_ARGS_EACH, unused)
31 
32 #define JS_BIND_DETAIL_EACH(z, n, return_type) \
33  emscripten::class_<std::function<return_type(JS_BIND_DETAIL_ARGS(n))>>( \
34  BOOST_PP_STRINGIZE(return_type) BOOST_PP_STRINGIZE(n) "ArgsFunctor") \
35  .constructor<>() \
36  .function("opcall", &std::function<return_type(JS_BIND_DETAIL_ARGS(n))>::operator());
37 
38 #define JS_BIND_DETAIL_GENERATE_BINDINGS() \
39  BOOST_PP_REPEAT(JS_BIND_MAX_ARITY, JS_BIND_DETAIL_EACH, void) \
40  BOOST_PP_REPEAT(JS_BIND_MAX_ARITY, JS_BIND_DETAIL_EACH, emscripten::val)
41 
42 #define JS_BIND_FUNCTION_TYPES_EACH(z, n, return_type) \
43  template <> \
44  struct functor_t<std::is_same<return_type, void>::value, n> \
45  { \
46  typedef ::std::function<return_type(JS_BIND_DETAIL_ARGS(n))> type; \
47  };
48 
49 #define JS_BIND_FUNCTION_TYPES() \
50  BOOST_PP_REPEAT(JS_BIND_MAX_ARITY, JS_BIND_FUNCTION_TYPES_EACH, void) \
51  BOOST_PP_REPEAT(JS_BIND_MAX_ARITY, JS_BIND_FUNCTION_TYPES_EACH, emscripten::val)
52 
53 #define JS_BIND_DETAIL_FWD(...) ::std::forward<decltype(__VA_ARGS__)>(__VA_ARGS__)
54 
55 namespace Nui
56 {
57 
65  template <class F, class... Args>
66  emscripten::val bind(F&& f, Args&&... args);
67 
68  namespace detail
69  {
70  template <typename... Args>
72 
73  template <>
75  {
76  static constexpr size_t value = 0;
77  };
78 
79  template <class T>
81  {
82  static constexpr size_t value = (std::is_placeholder<typename std::decay<T>::type>::value) ? 1 : 0;
83  };
84 
85  template <typename Arg, typename... Args>
86  struct placeholders_count<Arg, Args...>
87  {
88  static constexpr size_t value = one_if_placeholder<Arg>::value + placeholders_count<Args...>::value;
89  };
90  }
91 
92  template <const bool returns_void, const size_t arity>
93  struct functor_t;
94 
96 
97  template <class F, class... Args>
98  emscripten::val bind(F&& f, Args&&... args)
99  {
100  using emscripten::val;
101  using pre::type_traits::function_traits;
102 
103  using result_type = typename function_traits<std::decay_t<F>>::result_type;
104  auto bind_result = std::bind(std::forward<decltype(f)>(f), JS_BIND_DETAIL_FWD(args)...);
105 
106  using callback_t =
108  type;
109 
110  callback_t functor = bind_result;
111 
112  // We ensure the correct object will always be bound to the this of the function
113  auto functor_adapter =
114  emscripten::val(functor)["opcall"].call<emscripten::val>("bind", emscripten::val(functor));
115  return functor_adapter;
116  }
117 
118 }
119 
120 #endif // JS_BIND_HPP
#define JS_BIND_DETAIL_FWD(...)
Definition: functions.hpp:53
Definition: file_dialog.hpp:6
emscripten::val bind(F &&f, Args &&... args)
Equivalent of std::bind returning a javascript functor.
Definition: functions.hpp:98
JS_BIND_FUNCTION_TYPES()
emscripten::val val
Definition: val.hpp:5
Definition: functions.hpp:81
static constexpr size_t value
Definition: functions.hpp:82
Definition: functions.hpp:71
Definition: functions.hpp:93