Nui
Loading...
Searching...
No Matches
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 <traits/functions.hpp>
14
15#include <boost/preprocessor/repetition/repeat.hpp>
16#include <boost/preprocessor/punctuation/comma_if.hpp>
17#include <boost/preprocessor/stringize.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
55namespace 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
102 using result_type = typename Traits::FunctionTraits<std::decay_t<F>>::ReturnType;
103 auto bind_result = std::bind(std::forward<decltype(f)>(f), JS_BIND_DETAIL_FWD(args)...);
104
105 using callback_t =
107 type;
108
109 callback_t functor = bind_result;
110
111 // We ensure the correct object will always be bound to the this of the function
112 auto functor_adapter =
113 emscripten::val(functor)["opcall"].call<emscripten::val>("bind", emscripten::val(functor));
114 return functor_adapter;
115 }
116
117}
118
119#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()
Definition functions.hpp:81
static constexpr size_t value
Definition functions.hpp:82
Definition functions.hpp:71
Definition functions.hpp:93