aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChad Austin <caustin@gmail.com>2013-02-15 16:49:36 -0800
committerJukka Jylänki <jujjyl@gmail.com>2013-04-12 14:23:59 +0300
commitdd618d24fc2500ec49fe536936ea404e92cc7150 (patch)
treeb8a87b9f8f51afb57e09b703b1284956bebbeb57
parent51dfc764bd72ef54b00617e6dcedf017f52a53d0 (diff)
implement an api for allowing JS subclasses of C++ interfaces
-rwxr-xr-xsystem/include/emscripten/bind.h64
1 files changed, 63 insertions, 1 deletions
diff --git a/system/include/emscripten/bind.h b/system/include/emscripten/bind.h
index 28fe1f3a..a807be4c 100755
--- a/system/include/emscripten/bind.h
+++ b/system/include/emscripten/bind.h
@@ -278,6 +278,11 @@ namespace emscripten {
namespace internal {
template<typename ClassType, typename... Args>
+ ClassType* operator_new(Args... args) {
+ return new ClassType(args...);
+ }
+
+ template<typename ClassType, typename... Args>
ClassType* raw_constructor(
typename internal::BindingType<Args>::WireType... args
) {
@@ -595,7 +600,49 @@ namespace emscripten {
////////////////////////////////////////////////////////////////////////////////
// CLASSES
////////////////////////////////////////////////////////////////////////////////
- // TODO: support class definitions without constructors.
+
+ // abstract classes
+ template<typename T>
+ class wrapper : public T {
+ public:
+ wrapper(const val& wrapped)
+ : wrapped(wrapped)
+ {}
+
+ template<typename ReturnType, typename... Args>
+ ReturnType call(const char* name, Args... args) const {
+ return Caller<ReturnType, Args...>::call(wrapped, name, args...);
+ }
+
+ private:
+ // this class only exists because you can't partially specialize function templates
+ template<typename ReturnType, typename... Args>
+ struct Caller {
+ static ReturnType call(const val& v, const char* name, Args... args) {
+ return v.call(name, args...).template as<ReturnType>();
+ }
+ };
+
+ template<typename... Args>
+ struct Caller<void, Args...> {
+ static void call(const val& v, const char* name, Args... args) {
+ v.call_void(name, args...);
+ }
+ };
+
+ /*
+ void assertInitialized() {
+ if (!jsobj) {
+ internal::_embind_fatal_error(
+ "Cannot invoke call on uninitialized Javascript interface wrapper.", "JSInterface");
+ }
+ }*/
+ val wrapped;
+ };
+
+#define EMSCRIPTEN_WRAPPER(T) \
+ T(const ::emscripten::val& v): wrapper(v) {}
+
// TODO: support external class constructors
template<typename ClassType>
class class_ {
@@ -626,6 +673,21 @@ namespace emscripten {
return *this;
}
+ template<typename WrapperType>
+ class_& allow_subclass() {
+ using namespace internal;
+
+ // TODO: unique or anonymous name
+ class_<WrapperType>("WrapperType")
+ .template constructor<val>()
+ ;
+
+ return classmethod(
+ "implement",
+ &operator_new<WrapperType, val>,
+ allow_raw_pointer<ret_val>());
+ }
+
template<typename ReturnType, typename... Args, typename... Policies>
class_& method(const char* methodName, ReturnType (ClassType::*memberFunction)(Args...), Policies...) {
using namespace internal;