diff options
Diffstat (limited to 'system')
-rwxr-xr-x | system/include/emscripten/bind.h | 192 | ||||
-rw-r--r-- | system/include/emscripten/val.h | 57 | ||||
-rwxr-xr-x | system/include/emscripten/wire.h | 34 | ||||
-rwxr-xr-x | system/lib/embind/bind.cpp | 23 |
4 files changed, 191 insertions, 115 deletions
diff --git a/system/include/emscripten/bind.h b/system/include/emscripten/bind.h index 57e44c0c..4d2f4ac8 100755 --- a/system/include/emscripten/bind.h +++ b/system/include/emscripten/bind.h @@ -47,10 +47,15 @@ namespace emscripten { TYPEID floatType, const char* name); - void _embind_register_cstring( + void _embind_register_std_string( TYPEID stringType, const char* name); + void _embind_register_std_wstring( + TYPEID stringType, + size_t charSize, + const char* name); + void _embind_register_emval( TYPEID emvalType, const char* name); @@ -136,10 +141,12 @@ namespace emscripten { void _embind_register_class_property( TYPEID classType, const char* fieldName, - TYPEID fieldType, + TYPEID getterReturnType, GenericFunction getter, + void* getterContext, + TYPEID setterArgumentType, GenericFunction setter, - void* context); + void* setterContext); void _embind_register_class_class_function( TYPEID classType, @@ -223,6 +230,18 @@ namespace emscripten { } namespace internal { + template<typename ClassType, typename Signature> + struct MemberFunctionType { + typedef Signature (ClassType::*type); + }; + } + + template<typename Signature, typename ClassType> + typename internal::MemberFunctionType<ClassType, Signature>::type select_overload(Signature (ClassType::*fn)) { + return fn; + } + + namespace internal { template<typename ReturnType, typename... Args> struct Invoker { static typename internal::BindingType<ReturnType>::WireType invoke( @@ -277,8 +296,8 @@ namespace emscripten { } template<typename WrapperType, typename ClassType, typename... Args> - WrapperType wrapped_new(Args... args) { - return WrapperType(new ClassType(args...)); + WrapperType wrapped_new(Args&&... args) { + return WrapperType(new ClassType(std::forward<Args>(args)...)); } template<typename ClassType, typename... Args> @@ -711,28 +730,41 @@ namespace emscripten { template<typename T> class wrapper : public T { public: - wrapper(const val& wrapped) - : wrapped(wrapped) + explicit wrapper(val&& wrapped) + : wrapped(std::forward<val>(wrapped)) {} template<typename ReturnType, typename... Args> - ReturnType call(const char* name, Args... args) const { - return Caller<ReturnType, Args...>::call(wrapped, name, args...); + ReturnType call(const char* name, Args&&... args) const { + return Caller<ReturnType, Args...>::call(wrapped, name, std::forward<Args>(args)...); + } + + template<typename ReturnType, typename... Args, typename Default> + ReturnType optional_call(const char* name, Default def, Args&&... args) const { + if (has_function(name)) { + return Caller<ReturnType, Args...>::call(wrapped, name, std::forward<Args>(args)...); + } else { + return def(); + } } private: + bool has_function(const char* name) const { + return wrapped.has_function(name); + } + // 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>(); + static ReturnType call(const val& v, const char* name, Args&&... args) { + return v.call(name, std::forward<Args>(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...); + static void call(const val& v, const char* name, Args&&... args) { + v.call_void(name, std::forward<Args>(args)...); } }; @@ -740,7 +772,7 @@ namespace emscripten { }; #define EMSCRIPTEN_WRAPPER(T) \ - T(const ::emscripten::val& v): wrapper(v) {} + T(::emscripten::val&& v): wrapper(std::forward<::emscripten::val>(v)) {} namespace internal { struct NoBaseClass { @@ -971,7 +1003,23 @@ namespace emscripten { return *this; } - template<typename FieldType> + template<typename FieldType, typename = typename std::enable_if<!std::is_function<FieldType>::value>::type> + class_& property(const char* fieldName, const FieldType ClassType::*field) { + using namespace internal; + + _embind_register_class_property( + TypeID<ClassType>::get(), + fieldName, + TypeID<FieldType>::get(), + reinterpret_cast<GenericFunction>(&MemberAccess<ClassType, FieldType>::template getWire<ClassType>), + getContext(field), + 0, + 0, + 0); + return *this; + } + + template<typename FieldType, typename = typename std::enable_if<!std::is_function<FieldType>::value>::type> class_& property(const char* fieldName, FieldType ClassType::*field) { using namespace internal; @@ -980,11 +1028,46 @@ namespace emscripten { fieldName, TypeID<FieldType>::get(), reinterpret_cast<GenericFunction>(&MemberAccess<ClassType, FieldType>::template getWire<ClassType>), + getContext(field), + TypeID<FieldType>::get(), reinterpret_cast<GenericFunction>(&MemberAccess<ClassType, FieldType>::template setWire<ClassType>), getContext(field)); return *this; } + template<typename Getter> + class_& property(const char* fieldName, Getter getter) { + using namespace internal; + typedef GetterPolicy<Getter> GP; + _embind_register_class_property( + TypeID<ClassType>::get(), + fieldName, + TypeID<typename GP::ReturnType>::get(), + reinterpret_cast<GenericFunction>(&GP::template get<ClassType>), + GP::getContext(getter), + 0, + 0, + 0); + return *this; + } + + template<typename Getter, typename Setter> + class_& property(const char* fieldName, Getter getter, Setter setter) { + using namespace internal; + typedef GetterPolicy<Getter> GP; + typedef SetterPolicy<Setter> SP; + _embind_register_class_property( + TypeID<ClassType>::get(), + fieldName, + TypeID<typename GP::ReturnType>::get(), + reinterpret_cast<GenericFunction>(&GP::template get<ClassType>), + GP::getContext(getter), + TypeID<typename SP::ArgumentType>::get(), + reinterpret_cast<GenericFunction>(&SP::template set<ClassType>), + SP::getContext(setter)); + return *this; + } + template<typename ReturnType, typename... Args, typename... Policies> class_& class_function(const char* methodName, ReturnType (*classMethod)(Args...), Policies...) { using namespace internal; @@ -999,11 +1082,6 @@ namespace emscripten { reinterpret_cast<GenericFunction>(classMethod)); return *this; } - - template<typename ReturnType, typename... Args, typename... Policies> - class_& calloperator(const char* methodName, Policies... policies) { - return function(methodName, &ClassType::operator(), policies...); - } }; //////////////////////////////////////////////////////////////////////////////// @@ -1210,80 +1288,6 @@ namespace emscripten { typename std::aligned_storage<sizeof(T)>::type data; }; } - - //////////////////////////////////////////////////////////////////////////////// - // NEW INTERFACE - //////////////////////////////////////////////////////////////////////////////// - - class JSInterface { - public: - JSInterface(internal::EM_VAL handle) { - initialize(handle); - } - - JSInterface(const JSInterface& obj) - : jsobj(obj.jsobj) - {} - - template<typename ReturnType, typename... Args> - ReturnType call(const char* name, Args... args) { - assertInitialized(); - return Caller<ReturnType, Args...>::call(*jsobj, name, args...); - } - - static std::shared_ptr<JSInterface> cloneToSharedPtr(const JSInterface& i) { - return std::make_shared<JSInterface>(i); - } - - private: - void initialize(internal::EM_VAL handle) { - if (jsobj) { - internal::_embind_fatal_error( - "Cannot initialize interface wrapper twice", - "JSInterface"); - } - jsobj = val::take_ownership(handle); - } - - // this class only exists because you can't partially specialize function templates - template<typename ReturnType, typename... Args> - struct Caller { - static ReturnType call(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(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"); - } - } - - internal::optional<val> jsobj; - }; - - namespace internal { - extern JSInterface* create_js_interface(EM_VAL e); - } - - class register_js_interface { - public: - register_js_interface() { - _embind_register_interface( - internal::TypeID<JSInterface>::get(), - "JSInterface", - reinterpret_cast<internal::GenericFunction>(&internal::create_js_interface), - reinterpret_cast<internal::GenericFunction>(&internal::raw_destructor<JSInterface>)); - } - }; } namespace emscripten { diff --git a/system/include/emscripten/val.h b/system/include/emscripten/val.h index 91f775a7..09cad80e 100644 --- a/system/include/emscripten/val.h +++ b/system/include/emscripten/val.h @@ -8,6 +8,8 @@ namespace emscripten { namespace internal { // Implemented in JavaScript. Don't call these directly. extern "C" { + void _emval_register_symbol(const char*); + typedef struct _EM_VAL* EM_VAL; void _emval_incref(EM_VAL value); @@ -48,9 +50,23 @@ namespace emscripten { unsigned argCount, internal::TYPEID argTypes[] /*, ...*/); + bool _emval_has_function( + EM_VAL value, + const char* methodName); } } + template<const char* address> + struct symbol_registrar { + symbol_registrar() { + internal::_emval_register_symbol(address); + } + }; + +#define EMSCRIPTEN_SYMBOL(name) \ + static const char name##_symbol[] = #name; \ + static const symbol_registrar<name##_symbol> name##_registrar + class val { public: // missing operators: @@ -98,18 +114,24 @@ namespace emscripten { } template<typename T> - explicit val(const T& value) { + explicit val(T&& value) { typedef internal::BindingType<T> BT; auto taker = reinterpret_cast<internal::EM_VAL (*)(internal::TYPEID, typename BT::WireType)>(&internal::_emval_take_value); - handle = taker(internal::TypeID<T>::get(), BT::toWireType(value)); + handle = taker(internal::TypeID<T>::get(), BT::toWireType(std::forward<T>(value))); } val() = delete; - val(const char* v) + explicit val(const char* v) : handle(internal::_emval_new_cstring(v)) {} + val(val&& v) + : handle(v.handle) + { + v.handle = 0; + } + val(const val& v) : handle(v.handle) { @@ -120,6 +142,13 @@ namespace emscripten { internal::_emval_decref(handle); } + val& operator=(val&& v) { + internal::_emval_decref(handle); + handle = v.handle; + v.handle = 0; + return *this; + } + val& operator=(const val& v) { internal::_emval_incref(v.handle); internal::_emval_decref(handle); @@ -132,7 +161,7 @@ namespace emscripten { } template<typename... Args> - val new_(Args... args) const { + val new_(Args&&... args) const { using namespace internal; WithPolicies<>::ArgTypeList<Args...> argList; @@ -149,7 +178,7 @@ namespace emscripten { handle, argList.count, argList.types, - toWireType(args)...)); + toWireType(std::forward<Args>(args))...)); } template<typename T> @@ -163,7 +192,7 @@ namespace emscripten { } template<typename... Args> - val operator()(Args... args) { + val operator()(Args&&... args) { using namespace internal; WithPolicies<>::ArgTypeList<Args...> argList; @@ -178,11 +207,11 @@ namespace emscripten { handle, argList.count, argList.types, - toWireType(args)...)); + toWireType(std::forward<Args>(args))...)); } template<typename ...Args> - val call(const char* name, Args... args) const { + val call(const char* name, Args&&... args) const { using namespace internal; WithPolicies<>::ArgTypeList<Args...> argList; @@ -199,11 +228,11 @@ namespace emscripten { name, argList.count, argList.types, - toWireType(args)...)); + toWireType(std::forward<Args>(args))...)); } template<typename ...Args> - void call_void(const char* name, Args... args) const { + void call_void(const char* name, Args&&... args) const { using namespace internal; WithPolicies<>::ArgTypeList<Args...> argList; @@ -219,7 +248,11 @@ namespace emscripten { name, argList.count, argList.types, - toWireType(args)...); + toWireType(std::forward<Args>(args))...); + } + + bool has_function(const char* name) const { + return _emval_has_function(handle, name); } template<typename T> @@ -253,7 +286,7 @@ namespace emscripten { template<> struct BindingType<val> { typedef internal::EM_VAL WireType; - static WireType toWireType(val v) { + static WireType toWireType(const val& v) { _emval_incref(v.handle); return v.handle; } diff --git a/system/include/emscripten/wire.h b/system/include/emscripten/wire.h index 64114491..6fb15fc7 100755 --- a/system/include/emscripten/wire.h +++ b/system/include/emscripten/wire.h @@ -181,11 +181,35 @@ namespace emscripten { } }; + template<> + struct BindingType<std::wstring> { + typedef struct { + size_t length; + wchar_t data[1]; // trailing data + }* WireType; + static WireType toWireType(const std::wstring& v) { + WireType wt = (WireType)malloc(sizeof(size_t) + v.length() * sizeof(wchar_t)); + wt->length = v.length(); + wmemcpy(wt->data, v.data(), v.length()); + return wt; + } + static std::wstring fromWireType(WireType v) { + return std::wstring(v->data, v->length); + } + static void destroy(WireType v) { + free(v); + } + }; + template<typename T> struct BindingType<const T> : public BindingType<T> { }; template<typename T> + struct BindingType<T&> : public BindingType<T> { + }; + + template<typename T> struct BindingType<const T&> : public BindingType<T> { }; @@ -216,10 +240,14 @@ namespace emscripten { typedef typename std::remove_reference<T>::type ActualT; typedef ActualT* WireType; - static WireType toWireType(T v) { + static WireType toWireType(const T& v) { return new T(v); } + static WireType toWireType(T&& v) { + return new T(std::forward<T>(v)); + } + static ActualT& fromWireType(WireType p) { return *p; } @@ -262,8 +290,8 @@ namespace emscripten { {}; template<typename T> - auto toWireType(const T& v) -> typename BindingType<T>::WireType { - return BindingType<T>::toWireType(v); + auto toWireType(T&& v) -> typename BindingType<T>::WireType { + return BindingType<T>::toWireType(std::forward<T>(v)); } template<typename T> diff --git a/system/lib/embind/bind.cpp b/system/lib/embind/bind.cpp index deb55138..35d99dad 100755 --- a/system/lib/embind/bind.cpp +++ b/system/lib/embind/bind.cpp @@ -36,12 +36,22 @@ extern "C" { }
}
-namespace emscripten {
- namespace internal {
- JSInterface* create_js_interface(EM_VAL e) {
- return new JSInterface(e);
- }
+// TODO: fix in library.js or a proper emscripten libc
+extern "C" wchar_t *wmemset(wchar_t *dest, wchar_t c, size_t count) {
+ wchar_t *o = dest;
+ while (count--) {
+ *o++ = c;
+ }
+ return dest;
+}
+
+// TODO: fix in library.js or a proper emscripten libc
+extern "C" wchar_t *wmemcpy(wchar_t *dest, const wchar_t *src, size_t count) {
+ wchar_t *o = dest;
+ while (count--) {
+ *dest++ = *src++;
}
+ return dest;
}
EMSCRIPTEN_BINDINGS(native_and_builtin_types) {
@@ -64,6 +74,7 @@ EMSCRIPTEN_BINDINGS(native_and_builtin_types) { _embind_register_float(TypeID<float>::get(), "float");
_embind_register_float(TypeID<double>::get(), "double");
- _embind_register_cstring(TypeID<std::string>::get(), "std::string");
+ _embind_register_std_string(TypeID<std::string>::get(), "std::string");
+ _embind_register_std_wstring(TypeID<std::wstring>::get(), sizeof(wchar_t), "std::wstring");
_embind_register_emval(TypeID<val>::get(), "emscripten::val");
}
|