![]() System : Linux absol.cf 5.4.0-198-generic #218-Ubuntu SMP Fri Sep 27 20:18:53 UTC 2024 x86_64 User : www-data ( 33) PHP Version : 7.4.33 Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare, Directory : /proc/thread-self/root/usr/share/emscripten/system/include/emscripten/ |
Upload File : |
#pragma once #include <stddef.h> #include <assert.h> #include <string> #include <functional> #include <vector> #include <map> #include <type_traits> #include <emscripten/val.h> #include <emscripten/wire.h> namespace emscripten { enum class sharing_policy { NONE = 0, INTRUSIVE = 1, BY_EMVAL = 2, }; namespace internal { typedef long GenericEnumValue; typedef void (*GenericFunction)(); // Implemented in JavaScript. Don't call these directly. extern "C" { void _embind_fatal_error( const char* name, const char* payload) __attribute__((noreturn)); void _embind_register_void( TYPEID voidType, const char* name); void _embind_register_bool( TYPEID boolType, const char* name, size_t size, bool trueValue, bool falseValue); void _embind_register_integer( TYPEID integerType, const char* name, size_t size, long minRange, unsigned long maxRange); void _embind_register_float( TYPEID floatType, const char* name, size_t size); 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); void _embind_register_memory_view( TYPEID memoryViewType, unsigned typedArrayIndex, const char* name); void _embind_register_function( const char* name, unsigned argCount, const TYPEID argTypes[], const char* signature, GenericFunction invoker, GenericFunction function); void _embind_register_value_array( TYPEID tupleType, const char* name, const char* constructorSignature, GenericFunction constructor, const char* destructorSignature, GenericFunction destructor); void _embind_register_value_array_element( TYPEID tupleType, TYPEID getterReturnType, const char* getterSignature, GenericFunction getter, void* getterContext, TYPEID setterArgumentType, const char* setterSignature, GenericFunction setter, void* setterContext); void _embind_finalize_value_array(TYPEID tupleType); void _embind_register_value_object( TYPEID structType, const char* fieldName, const char* constructorSignature, GenericFunction constructor, const char* destructorSignature, GenericFunction destructor); void _embind_register_value_object_field( TYPEID structType, const char* fieldName, TYPEID getterReturnType, const char* getterSignature, GenericFunction getter, void* getterContext, TYPEID setterArgumentType, const char* setterSignature, GenericFunction setter, void* setterContext); void _embind_finalize_value_object(TYPEID structType); void _embind_register_class( TYPEID classType, TYPEID pointerType, TYPEID constPointerType, TYPEID baseClassType, const char* getActualTypeSignature, GenericFunction getActualType, const char* upcastSignature, GenericFunction upcast, const char* downcastSignature, GenericFunction downcast, const char* className, const char* destructorSignature, GenericFunction destructor); void _embind_register_class_constructor( TYPEID classType, unsigned argCount, const TYPEID argTypes[], const char* invokerSignature, GenericFunction invoker, GenericFunction constructor); void _embind_register_class_function( TYPEID classType, const char* methodName, unsigned argCount, const TYPEID argTypes[], const char* invokerSignature, GenericFunction invoker, void* context, unsigned isPureVirtual); void _embind_register_class_property( TYPEID classType, const char* fieldName, TYPEID getterReturnType, const char* getterSignature, GenericFunction getter, void* getterContext, TYPEID setterArgumentType, const char* setterSignature, GenericFunction setter, void* setterContext); void _embind_register_class_class_function( TYPEID classType, const char* methodName, unsigned argCount, const TYPEID argTypes[], const char* invokerSignature, GenericFunction invoker, GenericFunction method); EM_VAL _embind_create_inheriting_constructor( const char* constructorName, TYPEID wrapperType, EM_VAL properties); void _embind_register_enum( TYPEID enumType, const char* name, size_t size, bool isSigned); void _embind_register_smart_ptr( TYPEID pointerType, TYPEID pointeeType, const char* pointerName, sharing_policy sharingPolicy, const char* getPointeeSignature, GenericFunction getPointee, const char* constructorSignature, GenericFunction constructor, const char* shareSignature, GenericFunction share, const char* destructorSignature, GenericFunction destructor); void _embind_register_enum_value( TYPEID enumType, const char* valueName, GenericEnumValue value); void _embind_register_constant( const char* name, TYPEID constantType, uintptr_t value); } } } namespace emscripten { //////////////////////////////////////////////////////////////////////////////// // POLICIES //////////////////////////////////////////////////////////////////////////////// template<int Index> struct arg { static constexpr int index = Index + 1; }; struct ret_val { static constexpr int index = 0; }; /* template<typename Slot> struct allow_raw_pointer { template<typename InputType, int Index> struct Transform { typedef typename std::conditional< Index == Slot::index, internal::AllowedRawPointer<typename std::remove_pointer<InputType>::type>, InputType >::type type; }; }; */ // whitelist all raw pointers struct allow_raw_pointers { template<typename InputType, int Index> struct Transform { typedef typename std::conditional< std::is_pointer<InputType>::value, internal::AllowedRawPointer<typename std::remove_pointer<InputType>::type>, InputType >::type type; }; }; // this is temporary until arg policies are reworked template<typename Slot> struct allow_raw_pointer : public allow_raw_pointers { }; //////////////////////////////////////////////////////////////////////////////// // select_overload and select_const //////////////////////////////////////////////////////////////////////////////// template<typename Signature> typename std::add_pointer<Signature>::type select_overload(typename std::add_pointer<Signature>::type fn) { return fn; } 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; } template<typename ClassType, typename ReturnType, typename... Args> auto select_const(ReturnType (ClassType::*method)(Args...) const) -> decltype(method) { return method; } namespace internal { // this should be in <type_traits>, but alas, it's not template<typename T> struct remove_class; template<typename C, typename R, typename... A> struct remove_class<R(C::*)(A...)> { using type = R(A...); }; template<typename C, typename R, typename... A> struct remove_class<R(C::*)(A...) const> { using type = R(A...); }; template<typename C, typename R, typename... A> struct remove_class<R(C::*)(A...) volatile> { using type = R(A...); }; template<typename C, typename R, typename... A> struct remove_class<R(C::*)(A...) const volatile> { using type = R(A...); }; template<typename LambdaType> struct CalculateLambdaSignature { using type = typename std::add_pointer< typename remove_class< decltype(&LambdaType::operator()) >::type >::type; }; } template<typename LambdaType> typename internal::CalculateLambdaSignature<LambdaType>::type optional_override(const LambdaType& fp) { return fp; } //////////////////////////////////////////////////////////////////////////////// // Invoker //////////////////////////////////////////////////////////////////////////////// namespace internal { template<typename ReturnType, typename... Args> struct Invoker { static typename internal::BindingType<ReturnType>::WireType invoke( ReturnType (*fn)(Args...), typename internal::BindingType<Args>::WireType... args ) { return internal::BindingType<ReturnType>::toWireType( fn( internal::BindingType<Args>::fromWireType(args)... ) ); } }; template<typename... Args> struct Invoker<void, Args...> { static void invoke( void (*fn)(Args...), typename internal::BindingType<Args>::WireType... args ) { return fn( internal::BindingType<Args>::fromWireType(args)... ); } }; } //////////////////////////////////////////////////////////////////////////////// // SignatureCode, SignatureString //////////////////////////////////////////////////////////////////////////////// namespace internal { template<typename T> struct SignatureCode { static constexpr char get() { return 'i'; } }; template<> struct SignatureCode<void> { static constexpr char get() { return 'v'; } }; template<> struct SignatureCode<float> { static constexpr char get() { return 'f'; } }; template<> struct SignatureCode<double> { static constexpr char get() { return 'd'; } }; template<typename... T> struct SignatureString; template<> struct SignatureString<> { char c = 0; }; template<typename First, typename... Rest> struct SignatureString<First, Rest...> { constexpr SignatureString() : c(SignatureCode<First>::get()) {} char c; SignatureString<Rest...> rest; }; template<typename Return, typename... Args> const char* getSignature(Return (*)(Args...)) { static constexpr SignatureString<Return, Args...> sig; return &sig.c; } } //////////////////////////////////////////////////////////////////////////////// // FUNCTIONS //////////////////////////////////////////////////////////////////////////////// extern "C" { void* __getDynamicPointerType(void* p); } template<typename ReturnType, typename... Args, typename... Policies> void function(const char* name, ReturnType (*fn)(Args...), Policies...) { using namespace internal; typename WithPolicies<Policies...>::template ArgTypeList<ReturnType, Args...> args; auto invoker = &Invoker<ReturnType, Args...>::invoke; _embind_register_function( name, args.getCount(), args.getTypes(), getSignature(invoker), reinterpret_cast<GenericFunction>(invoker), reinterpret_cast<GenericFunction>(fn)); } namespace internal { template<typename ClassType, typename... Args> ClassType* operator_new(Args&&... args) { return new ClassType(std::forward<Args>(args)...); } template<typename WrapperType, typename ClassType, typename... Args> WrapperType wrapped_new(Args&&... args) { return WrapperType(new ClassType(std::forward<Args>(args)...)); } template<typename ClassType, typename... Args> ClassType* raw_constructor( typename internal::BindingType<Args>::WireType... args ) { return new ClassType( internal::BindingType<Args>::fromWireType(args)... ); } template<typename ClassType> void raw_destructor(ClassType* ptr) { delete ptr; } template<typename FunctionPointerType, typename ReturnType, typename ThisType, typename... Args> struct FunctionInvoker { static typename internal::BindingType<ReturnType>::WireType invoke( FunctionPointerType* function, typename internal::BindingType<ThisType>::WireType wireThis, typename internal::BindingType<Args>::WireType... args ) { return internal::BindingType<ReturnType>::toWireType( (*function)( internal::BindingType<ThisType>::fromWireType(wireThis), internal::BindingType<Args>::fromWireType(args)...) ); } }; template<typename FunctionPointerType, typename ThisType, typename... Args> struct FunctionInvoker<FunctionPointerType, void, ThisType, Args...> { static void invoke( FunctionPointerType* function, typename internal::BindingType<ThisType>::WireType wireThis, typename internal::BindingType<Args>::WireType... args ) { (*function)( internal::BindingType<ThisType>::fromWireType(wireThis), internal::BindingType<Args>::fromWireType(args)...); } }; template<typename MemberPointer, typename ReturnType, typename ThisType, typename... Args> struct MethodInvoker { static typename internal::BindingType<ReturnType>::WireType invoke( const MemberPointer& method, typename internal::BindingType<ThisType>::WireType wireThis, typename internal::BindingType<Args>::WireType... args ) { return internal::BindingType<ReturnType>::toWireType( (internal::BindingType<ThisType>::fromWireType(wireThis)->*method)( internal::BindingType<Args>::fromWireType(args)... ) ); } }; template<typename MemberPointer, typename ThisType, typename... Args> struct MethodInvoker<MemberPointer, void, ThisType, Args...> { static void invoke( const MemberPointer& method, typename internal::BindingType<ThisType>::WireType wireThis, typename internal::BindingType<Args>::WireType... args ) { return (internal::BindingType<ThisType>::fromWireType(wireThis)->*method)( internal::BindingType<Args>::fromWireType(args)... ); } }; template<typename InstanceType, typename MemberType> struct MemberAccess { typedef MemberType InstanceType::*MemberPointer; typedef internal::BindingType<MemberType> MemberBinding; typedef typename MemberBinding::WireType WireType; template<typename ClassType> static WireType getWire( const MemberPointer& field, const ClassType& ptr ) { return MemberBinding::toWireType(ptr.*field); } template<typename ClassType> static void setWire( const MemberPointer& field, ClassType& ptr, WireType value ) { ptr.*field = MemberBinding::fromWireType(value); } }; // TODO: This could do a reinterpret-cast if sizeof(T) === sizeof(void*) template<typename T> inline T* getContext(const T& t) { // not a leak because this is called once per binding return new T(t); } template<typename T> struct GetterPolicy; template<typename GetterReturnType, typename GetterThisType> struct GetterPolicy<GetterReturnType (GetterThisType::*)() const> { typedef GetterReturnType ReturnType; typedef GetterReturnType (GetterThisType::*Context)() const; typedef internal::BindingType<ReturnType> Binding; typedef typename Binding::WireType WireType; template<typename ClassType> static WireType get(const Context& context, const ClassType& ptr) { return Binding::toWireType((ptr.*context)()); } static void* getContext(Context context) { return internal::getContext(context); } }; template<typename GetterReturnType, typename GetterThisType> struct GetterPolicy<GetterReturnType (*)(const GetterThisType&)> { typedef GetterReturnType ReturnType; typedef GetterReturnType (*Context)(const GetterThisType&); typedef internal::BindingType<ReturnType> Binding; typedef typename Binding::WireType WireType; template<typename ClassType> static WireType get(const Context& context, const ClassType& ptr) { return Binding::toWireType(context(ptr)); } static void* getContext(Context context) { return internal::getContext(context); } }; template<typename T> struct SetterPolicy; template<typename SetterThisType, typename SetterArgumentType> struct SetterPolicy<void (SetterThisType::*)(SetterArgumentType)> { typedef SetterArgumentType ArgumentType; typedef void (SetterThisType::*Context)(SetterArgumentType); typedef internal::BindingType<SetterArgumentType> Binding; typedef typename Binding::WireType WireType; template<typename ClassType> static void set(const Context& context, ClassType& ptr, WireType wt) { (ptr.*context)(Binding::fromWireType(wt)); } static void* getContext(Context context) { return internal::getContext(context); } }; template<typename SetterThisType, typename SetterArgumentType> struct SetterPolicy<void (*)(SetterThisType&, SetterArgumentType)> { typedef SetterArgumentType ArgumentType; typedef void (*Context)(SetterThisType&, SetterArgumentType); typedef internal::BindingType<SetterArgumentType> Binding; typedef typename Binding::WireType WireType; template<typename ClassType> static void set(const Context& context, ClassType& ptr, WireType wt) { context(ptr, Binding::fromWireType(wt)); } static void* getContext(Context context) { return internal::getContext(context); } }; class noncopyable { protected: noncopyable() {} ~noncopyable() {} private: noncopyable(const noncopyable&) = delete; const noncopyable& operator=(const noncopyable&) = delete; }; template<typename ClassType, typename ElementType> typename BindingType<ElementType>::WireType get_by_index(int index, ClassType& ptr) { return BindingType<ElementType>::toWireType(ptr[index]); } template<typename ClassType, typename ElementType> void set_by_index(int index, ClassType& ptr, typename BindingType<ElementType>::WireType wt) { ptr[index] = BindingType<ElementType>::fromWireType(wt); } } template<int Index> struct index { }; //////////////////////////////////////////////////////////////////////////////// // VALUE TUPLES //////////////////////////////////////////////////////////////////////////////// template<typename ClassType> class value_array : public internal::noncopyable { public: typedef ClassType class_type; value_array(const char* name) { using namespace internal; auto constructor = &raw_constructor<ClassType>; auto destructor = &raw_destructor<ClassType>; _embind_register_value_array( TypeID<ClassType>::get(), name, getSignature(constructor), reinterpret_cast<GenericFunction>(constructor), getSignature(destructor), reinterpret_cast<GenericFunction>(destructor)); } ~value_array() { using namespace internal; _embind_finalize_value_array(TypeID<ClassType>::get()); } template<typename InstanceType, typename ElementType> value_array& element(ElementType InstanceType::*field) { using namespace internal; auto getter = &MemberAccess<InstanceType, ElementType> ::template getWire<ClassType>; auto setter = &MemberAccess<InstanceType, ElementType> ::template setWire<ClassType>; _embind_register_value_array_element( TypeID<ClassType>::get(), TypeID<ElementType>::get(), getSignature(getter), reinterpret_cast<GenericFunction>(getter), getContext(field), TypeID<ElementType>::get(), getSignature(setter), reinterpret_cast<GenericFunction>(setter), getContext(field)); return *this; } template<typename Getter, typename Setter> value_array& element(Getter getter, Setter setter) { using namespace internal; typedef GetterPolicy<Getter> GP; typedef SetterPolicy<Setter> SP; auto g = &GP::template get<ClassType>; auto s = &SP::template set<ClassType>; _embind_register_value_array_element( TypeID<ClassType>::get(), TypeID<typename GP::ReturnType>::get(), getSignature(g), reinterpret_cast<GenericFunction>(g), GP::getContext(getter), TypeID<typename SP::ArgumentType>::get(), getSignature(s), reinterpret_cast<GenericFunction>(s), SP::getContext(setter)); return *this; } template<int Index> value_array& element(index<Index>) { using namespace internal; ClassType* null = 0; typedef typename std::remove_reference<decltype((*null)[Index])>::type ElementType; auto getter = &internal::get_by_index<ClassType, ElementType>; auto setter = &internal::set_by_index<ClassType, ElementType>; _embind_register_value_array_element( TypeID<ClassType>::get(), TypeID<ElementType>::get(), getSignature(getter), reinterpret_cast<GenericFunction>(getter), reinterpret_cast<void*>(Index), TypeID<ElementType>::get(), getSignature(setter), reinterpret_cast<GenericFunction>(setter), reinterpret_cast<void*>(Index)); return *this; } }; //////////////////////////////////////////////////////////////////////////////// // VALUE STRUCTS //////////////////////////////////////////////////////////////////////////////// template<typename ClassType> class value_object : public internal::noncopyable { public: typedef ClassType class_type; value_object(const char* name) { using namespace internal; auto ctor = &raw_constructor<ClassType>; auto dtor = &raw_destructor<ClassType>; _embind_register_value_object( TypeID<ClassType>::get(), name, getSignature(ctor), reinterpret_cast<GenericFunction>(ctor), getSignature(dtor), reinterpret_cast<GenericFunction>(dtor)); } ~value_object() { using namespace internal; _embind_finalize_value_object(internal::TypeID<ClassType>::get()); } template<typename InstanceType, typename FieldType> value_object& field(const char* fieldName, FieldType InstanceType::*field) { using namespace internal; auto getter = &MemberAccess<InstanceType, FieldType> ::template getWire<ClassType>; auto setter = &MemberAccess<InstanceType, FieldType> ::template setWire<ClassType>; _embind_register_value_object_field( TypeID<ClassType>::get(), fieldName, TypeID<FieldType>::get(), getSignature(getter), reinterpret_cast<GenericFunction>(getter), getContext(field), TypeID<FieldType>::get(), getSignature(setter), reinterpret_cast<GenericFunction>(setter), getContext(field)); return *this; } template<typename Getter, typename Setter> value_object& field( const char* fieldName, Getter getter, Setter setter ) { using namespace internal; typedef GetterPolicy<Getter> GP; typedef SetterPolicy<Setter> SP; auto g = &GP::template get<ClassType>; auto s = &SP::template set<ClassType>; _embind_register_value_object_field( TypeID<ClassType>::get(), fieldName, TypeID<typename GP::ReturnType>::get(), getSignature(g), reinterpret_cast<GenericFunction>(g), GP::getContext(getter), TypeID<typename SP::ArgumentType>::get(), getSignature(s), reinterpret_cast<GenericFunction>(s), SP::getContext(setter)); return *this; } template<int Index> value_object& field(const char* fieldName, index<Index>) { using namespace internal; ClassType* null = 0; typedef typename std::remove_reference<decltype((*null)[Index])>::type ElementType; auto getter = &internal::get_by_index<ClassType, ElementType>; auto setter = &internal::set_by_index<ClassType, ElementType>; _embind_register_value_object_field( TypeID<ClassType>::get(), fieldName, TypeID<ElementType>::get(), getSignature(getter), reinterpret_cast<GenericFunction>(getter), reinterpret_cast<void*>(Index), TypeID<ElementType>::get(), getSignature(setter), reinterpret_cast<GenericFunction>(setter), reinterpret_cast<void*>(Index)); return *this; } }; //////////////////////////////////////////////////////////////////////////////// // SMART POINTERS //////////////////////////////////////////////////////////////////////////////// template<typename PointerType> struct default_smart_ptr_trait { static sharing_policy get_sharing_policy() { return sharing_policy::NONE; } static void* share(void* v) { return 0; // no sharing } static PointerType* construct_null() { return new PointerType; } }; // specialize if you have a different pointer type template<typename PointerType> struct smart_ptr_trait : public default_smart_ptr_trait<PointerType> { typedef typename PointerType::element_type element_type; static element_type* get(const PointerType& ptr) { return ptr.get(); } }; template<typename PointeeType> struct smart_ptr_trait<std::shared_ptr<PointeeType>> { typedef std::shared_ptr<PointeeType> PointerType; typedef typename PointerType::element_type element_type; static element_type* get(const PointerType& ptr) { return ptr.get(); } static sharing_policy get_sharing_policy() { return sharing_policy::BY_EMVAL; } static std::shared_ptr<PointeeType>* share(PointeeType* p, internal::EM_VAL v) { return new std::shared_ptr<PointeeType>( p, val_deleter(val::take_ownership(v))); } static PointerType* construct_null() { return new PointerType; } private: class val_deleter { public: val_deleter() = delete; explicit val_deleter(val v) : v(v) {} void operator()(void const*) { v(); // eventually we'll need to support emptied out val v = val::undefined(); } private: val v; }; }; //////////////////////////////////////////////////////////////////////////////// // CLASSES //////////////////////////////////////////////////////////////////////////////// namespace internal { class WrapperBase { public: void setNotifyJSOnDestruction(bool notify) { notifyJSOnDestruction = notify; } protected: bool notifyJSOnDestruction = false; }; } // abstract classes template<typename T> class wrapper : public T, public internal::WrapperBase { public: typedef T class_type; template<typename... Args> explicit wrapper(val&& wrapped, Args&&... args) : T(std::forward<Args>(args)...) , wrapped(std::forward<val>(wrapped)) {} ~wrapper() { if (notifyJSOnDestruction) { call<void>("__destruct"); } } template<typename ReturnType, typename... Args> ReturnType call(const char* name, Args&&... args) const { return wrapped.call<ReturnType>(name, std::forward<Args>(args)...); } private: val wrapped; }; #define EMSCRIPTEN_WRAPPER(T) \ template<typename... Args> \ T(::emscripten::val&& v, Args&&... args) \ : wrapper(std::forward<::emscripten::val>(v), std::forward<Args>(args)...) \ {} namespace internal { struct NoBaseClass { template<typename ClassType> static void verify() { } static TYPEID get() { return nullptr; } template<typename ClassType> static GenericFunction getUpcaster() { return nullptr; } template<typename ClassType> static GenericFunction getDowncaster() { return nullptr; } }; // NOTE: this returns the class type, not the pointer type template<typename T> inline TYPEID getActualType(T* ptr) { return getLightTypeID(*ptr); }; } template<typename BaseClass> struct base { typedef BaseClass class_type; template<typename ClassType> static void verify() { static_assert(!std::is_same<ClassType, BaseClass>::value, "Base must not have same type as class"); static_assert(std::is_base_of<BaseClass, ClassType>::value, "Derived class must derive from base"); } static internal::TYPEID get() { return internal::TypeID<BaseClass>::get(); } template<typename ClassType> using Upcaster = BaseClass* (*)(ClassType*); template<typename ClassType> using Downcaster = ClassType* (*)(BaseClass*); template<typename ClassType> static Upcaster<ClassType> getUpcaster() { return &convertPointer<ClassType, BaseClass>; } template<typename ClassType> static Downcaster<ClassType> getDowncaster() { return &convertPointer<BaseClass, ClassType>; } template<typename From, typename To> static To* convertPointer(From* ptr) { return static_cast<To*>(ptr); } }; namespace internal { template<typename T> struct SmartPtrIfNeeded { template<typename U> SmartPtrIfNeeded(U& cls, const char* smartPtrName) { cls.template smart_ptr<T>(smartPtrName); } }; template<typename T> struct SmartPtrIfNeeded<T*> { template<typename U> SmartPtrIfNeeded(U&, const char*) { } }; template<typename WrapperType> val wrapped_extend(const std::string& name, const val& properties) { return val::take_ownership(_embind_create_inheriting_constructor( name.c_str(), TypeID<WrapperType>::get(), properties.__get_handle())); } }; struct pure_virtual { template<typename InputType, int Index> struct Transform { typedef InputType type; }; }; namespace internal { template<typename... Policies> struct isPureVirtual; template<typename... Rest> struct isPureVirtual<pure_virtual, Rest...> { static constexpr bool value = true; }; template<typename T, typename... Rest> struct isPureVirtual<T, Rest...> { static constexpr bool value = isPureVirtual<Rest...>::value; }; template<> struct isPureVirtual<> { static constexpr bool value = false; }; } template<typename... ConstructorArgs> struct constructor { }; template<typename ClassType, typename BaseSpecifier = internal::NoBaseClass> class class_ { public: typedef ClassType class_type; typedef BaseSpecifier base_specifier; class_() = delete; EMSCRIPTEN_ALWAYS_INLINE explicit class_(const char* name) { using namespace internal; BaseSpecifier::template verify<ClassType>(); auto _getActualType = &getActualType<ClassType>; auto upcast = BaseSpecifier::template getUpcaster<ClassType>(); auto downcast = BaseSpecifier::template getDowncaster<ClassType>(); auto destructor = &raw_destructor<ClassType>; _embind_register_class( TypeID<ClassType>::get(), TypeID<AllowedRawPointer<ClassType>>::get(), TypeID<AllowedRawPointer<const ClassType>>::get(), BaseSpecifier::get(), getSignature(_getActualType), reinterpret_cast<GenericFunction>(_getActualType), getSignature(upcast), reinterpret_cast<GenericFunction>(upcast), getSignature(downcast), reinterpret_cast<GenericFunction>(downcast), name, getSignature(destructor), reinterpret_cast<GenericFunction>(destructor)); } template<typename PointerType> EMSCRIPTEN_ALWAYS_INLINE const class_& smart_ptr(const char* name) const { using namespace internal; typedef smart_ptr_trait<PointerType> PointerTrait; typedef typename PointerTrait::element_type PointeeType; static_assert(std::is_same<ClassType, typename std::remove_cv<PointeeType>::type>::value, "smart pointer must point to this class"); auto get = &PointerTrait::get; auto construct_null = &PointerTrait::construct_null; auto share = &PointerTrait::share; auto destructor = &raw_destructor<PointerType>; _embind_register_smart_ptr( TypeID<PointerType>::get(), TypeID<PointeeType>::get(), name, PointerTrait::get_sharing_policy(), getSignature(get), reinterpret_cast<GenericFunction>(get), getSignature(construct_null), reinterpret_cast<GenericFunction>(construct_null), getSignature(share), reinterpret_cast<GenericFunction>(share), getSignature(destructor), reinterpret_cast<GenericFunction>(destructor)); return *this; }; template<typename... ConstructorArgs, typename... Policies> EMSCRIPTEN_ALWAYS_INLINE const class_& constructor(Policies... policies) const { return constructor( &internal::operator_new<ClassType, ConstructorArgs...>, policies...); } template<typename... Args, typename ReturnType, typename... Policies> EMSCRIPTEN_ALWAYS_INLINE const class_& constructor(ReturnType (*factory)(Args...), Policies...) const { using namespace internal; // TODO: allows all raw pointers... policies need a rethink typename WithPolicies<allow_raw_pointers, Policies...>::template ArgTypeList<ReturnType, Args...> args; auto invoke = &Invoker<ReturnType, Args...>::invoke; _embind_register_class_constructor( TypeID<ClassType>::get(), args.getCount(), args.getTypes(), getSignature(invoke), reinterpret_cast<GenericFunction>(invoke), reinterpret_cast<GenericFunction>(factory)); return *this; } template<typename SmartPtr, typename... Args, typename... Policies> EMSCRIPTEN_ALWAYS_INLINE const class_& smart_ptr_constructor(const char* smartPtrName, SmartPtr (*factory)(Args...), Policies...) const { using namespace internal; smart_ptr<SmartPtr>(smartPtrName); typename WithPolicies<Policies...>::template ArgTypeList<SmartPtr, Args...> args; auto invoke = &Invoker<SmartPtr, Args...>::invoke; _embind_register_class_constructor( TypeID<ClassType>::get(), args.getCount(), args.getTypes(), getSignature(invoke), reinterpret_cast<GenericFunction>(invoke), reinterpret_cast<GenericFunction>(factory)); return *this; } template<typename WrapperType, typename PointerType = WrapperType*, typename... ConstructorArgs> EMSCRIPTEN_ALWAYS_INLINE const class_& allow_subclass( const char* wrapperClassName, const char* pointerName = "<UnknownPointerName>", ::emscripten::constructor<ConstructorArgs...> = ::emscripten::constructor<ConstructorArgs...>() ) const { using namespace internal; auto cls = class_<WrapperType, base<ClassType>>(wrapperClassName) .function("notifyOnDestruction", select_overload<void(WrapperType&)>([](WrapperType& wrapper) { wrapper.setNotifyJSOnDestruction(true); })) ; SmartPtrIfNeeded<PointerType> _(cls, pointerName); return class_function( "implement", &wrapped_new<PointerType, WrapperType, val, ConstructorArgs...>, allow_raw_pointer<ret_val>()) .class_function( "extend", &wrapped_extend<WrapperType>) ; } template<typename WrapperType, typename... ConstructorArgs> EMSCRIPTEN_ALWAYS_INLINE const class_& allow_subclass( const char* wrapperClassName, ::emscripten::constructor<ConstructorArgs...> constructor ) const { return allow_subclass<WrapperType, WrapperType*>(wrapperClassName, "<UnknownPointerName>", constructor); } template<typename ReturnType, typename... Args, typename... Policies> EMSCRIPTEN_ALWAYS_INLINE const class_& function(const char* methodName, ReturnType (ClassType::*memberFunction)(Args...), Policies...) const { using namespace internal; auto invoker = &MethodInvoker<decltype(memberFunction), ReturnType, ClassType*, Args...>::invoke; typename WithPolicies<Policies...>::template ArgTypeList<ReturnType, AllowedRawPointer<ClassType>, Args...> args; _embind_register_class_function( TypeID<ClassType>::get(), methodName, args.getCount(), args.getTypes(), getSignature(invoker), reinterpret_cast<GenericFunction>(invoker), getContext(memberFunction), isPureVirtual<Policies...>::value); return *this; } template<typename ReturnType, typename... Args, typename... Policies> EMSCRIPTEN_ALWAYS_INLINE const class_& function(const char* methodName, ReturnType (ClassType::*memberFunction)(Args...) const, Policies...) const { using namespace internal; auto invoker = &MethodInvoker<decltype(memberFunction), ReturnType, const ClassType*, Args...>::invoke; typename WithPolicies<Policies...>::template ArgTypeList<ReturnType, AllowedRawPointer<const ClassType>, Args...> args; _embind_register_class_function( TypeID<ClassType>::get(), methodName, args.getCount(), args.getTypes(), getSignature(invoker), reinterpret_cast<GenericFunction>(invoker), getContext(memberFunction), isPureVirtual<Policies...>::value); return *this; } template<typename ReturnType, typename ThisType, typename... Args, typename... Policies> EMSCRIPTEN_ALWAYS_INLINE const class_& function(const char* methodName, ReturnType (*function)(ThisType, Args...), Policies...) const { using namespace internal; typename WithPolicies<Policies...>::template ArgTypeList<ReturnType, ThisType, Args...> args; auto invoke = &FunctionInvoker<decltype(function), ReturnType, ThisType, Args...>::invoke; _embind_register_class_function( TypeID<ClassType>::get(), methodName, args.getCount(), args.getTypes(), getSignature(invoke), reinterpret_cast<GenericFunction>(invoke), getContext(function), false); return *this; } template<typename FieldType, typename = typename std::enable_if<!std::is_function<FieldType>::value>::type> EMSCRIPTEN_ALWAYS_INLINE const class_& property(const char* fieldName, const FieldType ClassType::*field) const { using namespace internal; auto getter = &MemberAccess<ClassType, FieldType>::template getWire<ClassType>; _embind_register_class_property( TypeID<ClassType>::get(), fieldName, TypeID<FieldType>::get(), getSignature(getter), reinterpret_cast<GenericFunction>(getter), getContext(field), 0, 0, 0, 0); return *this; } template<typename FieldType, typename = typename std::enable_if<!std::is_function<FieldType>::value>::type> EMSCRIPTEN_ALWAYS_INLINE const class_& property(const char* fieldName, FieldType ClassType::*field) const { using namespace internal; auto getter = &MemberAccess<ClassType, FieldType>::template getWire<ClassType>; auto setter = &MemberAccess<ClassType, FieldType>::template setWire<ClassType>; _embind_register_class_property( TypeID<ClassType>::get(), fieldName, TypeID<FieldType>::get(), getSignature(getter), reinterpret_cast<GenericFunction>(getter), getContext(field), TypeID<FieldType>::get(), getSignature(setter), reinterpret_cast<GenericFunction>(setter), getContext(field)); return *this; } template<typename Getter> EMSCRIPTEN_ALWAYS_INLINE const class_& property(const char* fieldName, Getter getter) const { using namespace internal; typedef GetterPolicy<Getter> GP; auto gter = &GP::template get<ClassType>; _embind_register_class_property( TypeID<ClassType>::get(), fieldName, TypeID<typename GP::ReturnType>::get(), getSignature(gter), reinterpret_cast<GenericFunction>(gter), GP::getContext(getter), 0, 0, 0, 0); return *this; } template<typename Getter, typename Setter> EMSCRIPTEN_ALWAYS_INLINE const class_& property(const char* fieldName, Getter getter, Setter setter) const { using namespace internal; typedef GetterPolicy<Getter> GP; typedef SetterPolicy<Setter> SP; auto gter = &GP::template get<ClassType>; auto ster = &SP::template set<ClassType>; _embind_register_class_property( TypeID<ClassType>::get(), fieldName, TypeID<typename GP::ReturnType>::get(), getSignature(gter), reinterpret_cast<GenericFunction>(gter), GP::getContext(getter), TypeID<typename SP::ArgumentType>::get(), getSignature(ster), reinterpret_cast<GenericFunction>(ster), SP::getContext(setter)); return *this; } template<typename ReturnType, typename... Args, typename... Policies> EMSCRIPTEN_ALWAYS_INLINE const class_& class_function(const char* methodName, ReturnType (*classMethod)(Args...), Policies...) const { using namespace internal; typename WithPolicies<Policies...>::template ArgTypeList<ReturnType, Args...> args; auto invoke = &internal::Invoker<ReturnType, Args...>::invoke; _embind_register_class_class_function( TypeID<ClassType>::get(), methodName, args.getCount(), args.getTypes(), getSignature(invoke), reinterpret_cast<internal::GenericFunction>(invoke), reinterpret_cast<GenericFunction>(classMethod)); return *this; } }; //////////////////////////////////////////////////////////////////////////////// // VECTORS //////////////////////////////////////////////////////////////////////////////// namespace internal { template<typename VectorType> struct VectorAccess { static val get( const VectorType& v, typename VectorType::size_type index ) { if (index < v.size()) { return val(v[index]); } else { return val::undefined(); } } static bool set( VectorType& v, typename VectorType::size_type index, const typename VectorType::value_type& value ) { v[index] = value; return true; } }; } template<typename T> class_<std::vector<T>> register_vector(const char* name) { typedef std::vector<T> VecType; void (VecType::*push_back)(const T&) = &VecType::push_back; return class_<std::vector<T>>(name) .template constructor<>() .function("push_back", push_back) .function("size", &VecType::size) .function("get", &internal::VectorAccess<VecType>::get) .function("set", &internal::VectorAccess<VecType>::set) ; } //////////////////////////////////////////////////////////////////////////////// // MAPS //////////////////////////////////////////////////////////////////////////////// namespace internal { template<typename MapType> struct MapAccess { static val get( const MapType& m, const typename MapType::key_type& k ) { auto i = m.find(k); if (i == m.end()) { return val::undefined(); } else { return val(i->second); } } static void set( MapType& m, const typename MapType::key_type& k, const typename MapType::mapped_type& v ) { m[k] = v; } }; } template<typename K, typename V> class_<std::map<K, V>> register_map(const char* name) { typedef std::map<K,V> MapType; return class_<MapType>(name) .template constructor<>() .function("size", &MapType::size) .function("get", internal::MapAccess<MapType>::get) .function("set", internal::MapAccess<MapType>::set) ; } //////////////////////////////////////////////////////////////////////////////// // ENUMS //////////////////////////////////////////////////////////////////////////////// template<typename EnumType> class enum_ { public: typedef EnumType enum_type; enum_(const char* name) { using namespace internal; _embind_register_enum( internal::TypeID<EnumType>::get(), name, sizeof(EnumType), std::is_signed<typename std::underlying_type<EnumType>::type>::value); } enum_& value(const char* name, EnumType value) { using namespace internal; // TODO: there's still an issue here. // if EnumType is an unsigned long, then JS may receive it as a signed long static_assert(sizeof(value) <= sizeof(internal::GenericEnumValue), "enum type must fit in a GenericEnumValue"); _embind_register_enum_value( internal::TypeID<EnumType>::get(), name, static_cast<internal::GenericEnumValue>(value)); return *this; } }; //////////////////////////////////////////////////////////////////////////////// // CONSTANTS //////////////////////////////////////////////////////////////////////////////// namespace internal { template<typename T> uintptr_t asGenericValue(T t) { return static_cast<uintptr_t>(t); } template<typename T> uintptr_t asGenericValue(T* p) { return reinterpret_cast<uintptr_t>(p); } } template<typename ConstantType> void constant(const char* name, const ConstantType& v) { using namespace internal; typedef BindingType<const ConstantType&> BT; _embind_register_constant( name, TypeID<const ConstantType&>::get(), asGenericValue(BT::toWireType(v))); } } #define EMSCRIPTEN_BINDINGS(name) \ static struct EmscriptenBindingInitializer_##name { \ EmscriptenBindingInitializer_##name(); \ } EmscriptenBindingInitializer_##name##_instance; \ EmscriptenBindingInitializer_##name::EmscriptenBindingInitializer_##name()