├── .gitignore ├── .nxxm ├── deps └── opts.wasm-cxx17 ├── LICENSE ├── README.md ├── js └── bind.hpp └── test ├── CMakeLists.txt ├── bind.html └── example.html /.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | *.swo 3 | *.swp 4 | *.swn 5 | -------------------------------------------------------------------------------- /.nxxm/deps: -------------------------------------------------------------------------------- 1 | { 2 | "cpp-pre/type_traits" : { "@" : "v2.0.0" }, 3 | "platform" : [ "Boost::+boost" ] 4 | } 5 | -------------------------------------------------------------------------------- /.nxxm/opts.wasm-cxx17: -------------------------------------------------------------------------------- 1 | set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --bind -s NO_EXIT_RUNTIME=1 ") 2 | set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} --bind -s NO_EXIT_RUNTIME=1") 3 | add_definitions(-g4) # Generates emscripten C++ sourcemaps 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017 Damien Buhl alias daminetreg (damien.buhl@lecbna.org) 2 | 3 | Boost Software License - Version 1.0 - August 17th, 2003 4 | 5 | Permission is hereby granted, free of charge, to any person or organization 6 | obtaining a copy of the software and accompanying documentation covered by 7 | this license (the "Software") to use, reproduce, display, distribute, 8 | execute, and transmit the Software, and to prepare derivative works of the 9 | Software, and to permit third-parties to whom the Software is furnished to 10 | do so, all subject to the following: 11 | 12 | The copyright notices in the Software and this entire statement, including 13 | the above license grant, this restriction and the following disclaimer, 14 | must be included in all copies of the Software, in whole or in part, and 15 | all derivative works of the Software, unless such copies or derivative 16 | works are solely in the form of machine-executable object code generated by 17 | a source language processor. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 22 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 23 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 24 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # js::bind 2 | `js::bind` makes any C++ function, member function or lambda as a Javascript callable callback for [Emscripten](http:://www.emscripten.org/). 3 | 4 | ## Easy to use 5 | It's header only. You can set-it-up in 0-time with : [`nxxm .`](https://nxxm.github.io/), add this to `.nxxm/deps` 6 | 7 | ``` 8 | { 9 | "nxxm/js-bind" : { "@" : "v0.0.3" } 10 | } 11 | ``` 12 | 13 | * [Simple Example in Browser](https://daminetreg.github.io/js-bind/example.html) : [src: ./test/example.html](./test/example.html) 14 | * [HTTP Request Example](https://daminetreg.github.io/js-bind/bind.html) : [src: ./test/bind.html](./test/bind.html) 15 | 16 | ```cpp 17 | 18 | using namespace std; 19 | using namespace std::placeholders; 20 | using emscripten::val; 21 | 22 | auto clickme_btn = val::global("document").call("getElementById", "clickme_btn"s); 23 | 24 | auto onclick = [](val event){ 25 | std::cout << "hello world ! " << std::endl; 26 | }; 27 | 28 | clickme_btn.set("onclick", js::bind(onclick, _1)); 29 | ``` 30 | 31 | ## License 32 | Please give copyright notice for this project : [Boost Software License](./LICENSE). 33 | 34 | ``` 35 | Copyright (c) 2017 Damien Buhl alias daminetreg (damien.buhl@lecbna.org) 36 | ``` 37 | 38 | * [Damien Buhl alias daminetreg](mailto:damien.buhl@lecbna.org) 39 | -------------------------------------------------------------------------------- /js/bind.hpp: -------------------------------------------------------------------------------- 1 | #ifndef JS_BIND_HPP 2 | #define JS_BIND_HPP 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include
 15 | 
 16 | #ifndef JS_BIND_MAX_ARITY
 17 |   /**
 18 |    * \brief JS_BIND_MAX_ARITY Defines how many arguments the javascript
 19 |    *        exported C++  std::function can have. 
 20 |    *        It defaults to 16, simply override it if you need more.
 21 |    */
 22 |   #define JS_BIND_MAX_ARITY 16
 23 | #endif
 24 | 
 25 | #define JS_BIND_DETAIL_ARGS_EACH(z, n, unused)                                 \
 26 |   BOOST_PP_COMMA_IF(n) val 
 27 | 
 28 | #define JS_BIND_DETAIL_ARGS(COUNT)                                             \
 29 |   BOOST_PP_REPEAT(COUNT, JS_BIND_DETAIL_ARGS_EACH, unused)
 30 | 
 31 | #define JS_BIND_DETAIL_EACH(z, n, return_type)                                 \
 32 |   emscripten::class_<                                                          \
 33 |     std::function<                                                             \
 34 |       return_type(JS_BIND_DETAIL_ARGS(n))                                      \
 35 |     >                                                                          \
 36 |   >(BOOST_PP_STRINGIZE(return_type) BOOST_PP_STRINGIZE(n) "ArgsFunctor")       \
 37 |     .constructor<>()                                                           \
 38 |     .function("opcall", &std::function<                                        \
 39 |       return_type(JS_BIND_DETAIL_ARGS(n))                                      \
 40 |     >::operator());                                                            \
 41 | 
 42 | 
 43 | 
 44 | 
 45 | #define JS_BIND_DETAIL_GENERATE_BINDINGS()                                     \
 46 |   BOOST_PP_REPEAT(JS_BIND_MAX_ARITY, JS_BIND_DETAIL_EACH, void)                \
 47 |   BOOST_PP_REPEAT(JS_BIND_MAX_ARITY, JS_BIND_DETAIL_EACH, val)                 \
 48 | 
 49 | 
 50 | #define JS_BIND_FUNCTION_TYPES_EACH(z, n, return_type)                         \
 51 |   template<>                                                                   \
 52 |   struct functor_t::value, n> {                \
 53 |     typedef ::std::function<                                                   \
 54 |       return_type(JS_BIND_DETAIL_ARGS(n))                                      \
 55 |     > type;                                                                    \
 56 |   };                                                                           \
 57 | 
 58 | #define JS_BIND_FUNCTION_TYPES()                                               \
 59 |   BOOST_PP_REPEAT(JS_BIND_MAX_ARITY, JS_BIND_FUNCTION_TYPES_EACH, void)        \
 60 |   BOOST_PP_REPEAT(JS_BIND_MAX_ARITY, JS_BIND_FUNCTION_TYPES_EACH, val)         \
 61 | 
 62 | 
 63 | #define JS_BIND_DETAIL_FWD(...) ::std::forward(__VA_ARGS__)
 64 | 
 65 | namespace js {
 66 | 
 67 |   /**
 68 |    * \brief Equivalent of [std::bind](http://en.cppreference.com/w/cpp/utility/functional/bind) returning a javascript functor.
 69 |    * \param f The lambda, function, member function to bind
 70 |    * \param args 
 71 |    * \return An emscripten::val representing a javascript functor with it's 
 72 |    *         this-scope bound correctly. It can be called from js or c++ with 
 73 |    *         the call operator ( *i.e.* `operator()` ).
 74 |    *         
 75 |    */
 76 |   template< class F, class... Args >
 77 |   emscripten::val bind( F&& f, Args&&... args );
 78 | 
 79 | 
 80 |   namespace detail {
 81 |     template struct placeholders_count;
 82 |    
 83 |     template<>
 84 |     struct placeholders_count<> {
 85 |       static constexpr size_t value = 0;
 86 |     };
 87 |    
 88 |     template 
 89 |     struct one_if_placeholder {
 90 |       static constexpr size_t value = 
 91 |         (std::is_placeholder::type>::value) ? 1 : 0;
 92 |     };
 93 |    
 94 |     template
 95 |     struct placeholders_count {
 96 |       static constexpr size_t value = 
 97 |         one_if_placeholder::value + placeholders_count::value;
 98 |     }; 
 99 |   }
100 | 
101 |   using emscripten::val;
102 | 
103 |   template
104 |   struct functor_t;
105 | 
106 |   JS_BIND_FUNCTION_TYPES();
107 | 
108 |   EMSCRIPTEN_BINDINGS(jsbindhpp) {
109 |     JS_BIND_DETAIL_GENERATE_BINDINGS()
110 |   }
111 |  
112 |   template< class F, class... Args >
113 |   emscripten::val bind( F&& f, Args&&... args ) {
114 |     using emscripten::val;
115 |     using pre::type_traits::function_traits;
116 | 
117 |     using result_type = typename function_traits>::result_type;
118 |     auto bind_result = std::bind( std::forward(f), JS_BIND_DETAIL_FWD(args)... );
119 | 
120 |       using callback_t = typename functor_t<
121 |         std::is_same< result_type, void>::value,
122 |         detail::placeholders_count::value
123 |       >::type;
124 | 
125 |       callback_t functor = bind_result;
126 | 
127 |       // We ensure the correct object will always be bound to the this of the function
128 |       auto functor_adapter = val(functor)["opcall"].call("bind", val(functor)); 
129 |       return functor_adapter;
130 |     }
131 | 
132 | }
133 | 
134 | #endif // JS_BIND_HPP
135 | 


--------------------------------------------------------------------------------
/test/CMakeLists.txt:
--------------------------------------------------------------------------------
 1 | add_definitions(-std=c++14)
 2 | 
 3 | if (CMAKE_BUILD_TYPE MATCHES Debug)
 4 |   add_definitions(-g4) # Generates emscripten C++ sourcemaps
 5 | endif()
 6 | 
 7 | # bind
 8 | add_executable(bind bind.cpp)
 9 | set_target_properties(bind PROPERTIES SUFFIX ".html" LINK_FLAGS " --bind -s  NO_EXIT_RUNTIME=1 ")
10 | target_link_libraries(bind cpp-js::js-bind)
11 | 
12 | # example
13 | add_executable(example example.cpp)
14 | set_target_properties(example PROPERTIES SUFFIX ".html" LINK_FLAGS " --bind -s  NO_EXIT_RUNTIME=1 ")
15 | target_link_libraries(example cpp-js::js-bind)
16 | 


--------------------------------------------------------------------------------
/test/bind.html:
--------------------------------------------------------------------------------
 1 | 
 2 | 
 3 | 
 4 |   
 5 | 
 6 |    
91 | 
92 | 
93 |   

Download some file

94 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /test/example.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 26 | 27 | 28 |

Call C++ back

29 | 30 | 31 | 32 | --------------------------------------------------------------------------------