diff options
Diffstat (limited to 'system')
-rwxr-xr-x[-rw-r--r--] | system/include/emscripten/bind.h | 1227 | ||||
-rw-r--r-- | system/include/emscripten/val.h | 224 | ||||
-rwxr-xr-x[-rw-r--r--] | system/include/emscripten/wire.h | 267 | ||||
-rwxr-xr-x | system/lib/embind/bind.cpp | 83 |
4 files changed, 1328 insertions, 473 deletions
diff --git a/system/include/emscripten/bind.h b/system/include/emscripten/bind.h index 55fda986..57e44c0c 100644..100755 --- a/system/include/emscripten/bind.h +++ b/system/include/emscripten/bind.h @@ -3,11 +3,20 @@ #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 void (*GenericFunction)(); typedef long GenericEnumValue; @@ -19,150 +28,205 @@ namespace emscripten { const char* payload) __attribute__((noreturn)); void _embind_register_void( - TypeID voidType, + TYPEID voidType, const char* name); void _embind_register_bool( - TypeID boolType, + TYPEID boolType, const char* name, bool trueValue, bool falseValue); void _embind_register_integer( - TypeID integerType, - const char* name); + TYPEID integerType, + const char* name, + long minRange, + unsigned long maxRange); void _embind_register_float( - TypeID floatType, + TYPEID floatType, const char* name); void _embind_register_cstring( - TypeID stringType, + TYPEID stringType, const char* name); void _embind_register_emval( - TypeID emvalType, + TYPEID emvalType, const char* name); void _embind_register_function( const char* name, - TypeID returnType, unsigned argCount, - TypeID argTypes[], + TYPEID argTypes[], GenericFunction invoker, GenericFunction function); void _embind_register_tuple( - TypeID tupleType, + TYPEID tupleType, const char* name, GenericFunction constructor, GenericFunction destructor); void _embind_register_tuple_element( - TypeID tupleType, - TypeID elementType, + TYPEID tupleType, + TYPEID getterReturnType, GenericFunction getter, + void* getterContext, + TYPEID setterArgumentType, GenericFunction setter, - size_t memberPointerSize, - void* memberPointer); - - void _embind_register_tuple_element_accessor( - TypeID tupleType, - TypeID elementType, - GenericFunction staticGetter, - size_t getterSize, - void* getter, - GenericFunction staticSetter, - size_t setterSize, - void* setter); + void* setterContext); + + void _embind_finalize_tuple(TYPEID tupleType); void _embind_register_struct( - TypeID structType, - const char* name, + TYPEID structType, + const char* fieldName, GenericFunction constructor, GenericFunction destructor); void _embind_register_struct_field( - TypeID structType, - const char* name, - TypeID fieldType, + TYPEID structType, + const char* fieldName, + TYPEID getterReturnType, GenericFunction getter, + void* getterContext, + TYPEID setterArgumentType, GenericFunction setter, - size_t memberPointerSize, - void* memberPointer); + void* setterContext); + + void _embind_finalize_struct(TYPEID structType); + + void _embind_register_smart_ptr( + TYPEID pointerType, + TYPEID pointeeType, + const char* pointerName, + sharing_policy sharingPolicy, + GenericFunction getPointee, + GenericFunction constructor, + GenericFunction share, + GenericFunction destructor); void _embind_register_class( - TypeID classType, + TYPEID classType, + TYPEID pointerType, + TYPEID constPointerType, + TYPEID baseClassType, + GenericFunction getActualType, + GenericFunction upcast, + GenericFunction downcast, const char* className, GenericFunction destructor); void _embind_register_class_constructor( - TypeID classType, + TYPEID classType, unsigned argCount, - TypeID argTypes[], + TYPEID argTypes[], + GenericFunction invoker, GenericFunction constructor); - void _embind_register_class_method( - TypeID classType, + void _embind_register_class_function( + TYPEID classType, const char* methodName, - TypeID returnType, unsigned argCount, - TypeID argTypes[], + TYPEID argTypes[], GenericFunction invoker, - size_t memberFunctionSize, - void* memberFunction); + void* context); - void _embind_register_class_field( - TypeID classType, + void _embind_register_class_property( + TYPEID classType, const char* fieldName, - TypeID fieldType, + TYPEID fieldType, GenericFunction getter, GenericFunction setter, - size_t memberPointerSize, - void* memberPointer); + void* context); - void _embind_register_class_classmethod( - TypeID classType, + void _embind_register_class_class_function( + TYPEID classType, const char* methodName, - TypeID returnType, unsigned argCount, - TypeID argTypes[], + TYPEID argTypes[], + GenericFunction invoker, GenericFunction method); void _embind_register_enum( - TypeID enumType, + TYPEID enumType, const char* name); void _embind_register_enum_value( - TypeID enumType, + TYPEID enumType, const char* valueName, GenericEnumValue value); void _embind_register_interface( - TypeID interfaceType, + TYPEID interfaceType, const char* name, GenericFunction constructor, GenericFunction destructor); + + void _embind_register_constant( + const char* name, + TYPEID constantType, + uintptr_t value); } + } +} - extern void registerStandardTypes(); +namespace emscripten { + //////////////////////////////////////////////////////////////////////////////// + // POLICIES + //////////////////////////////////////////////////////////////////////////////// - class BindingsDefinition { - public: - template<typename Function> - BindingsDefinition(Function fn) { - fn(); - } + 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 { + }; + + template<typename Signature> + typename std::add_pointer<Signature>::type select_overload(typename std::add_pointer<Signature>::type fn) { + return fn; } -} -namespace emscripten { namespace internal { template<typename ReturnType, typename... Args> struct Invoker { static typename internal::BindingType<ReturnType>::WireType invoke( - ReturnType (fn)(Args...), + ReturnType (*fn)(Args...), typename internal::BindingType<Args>::WireType... args ) { return internal::BindingType<ReturnType>::toWireType( @@ -176,7 +240,7 @@ namespace emscripten { template<typename... Args> struct Invoker<void, Args...> { static void invoke( - void (fn)(Args...), + void (*fn)(Args...), typename internal::BindingType<Args>::WireType... args ) { return fn( @@ -186,22 +250,38 @@ namespace emscripten { }; } - template<typename ReturnType, typename... Args> - void function(const char* name, ReturnType (fn)(Args...)) { - internal::registerStandardTypes(); + //////////////////////////////////////////////////////////////////////////////// + // FUNCTIONS + //////////////////////////////////////////////////////////////////////////////// + + extern "C" { + void* __getDynamicPointerType(void* p); + } - internal::ArgTypeList<Args...> args; - internal::_embind_register_function( + 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; + _embind_register_function( name, - internal::getTypeID<ReturnType>(), args.count, args.types, - reinterpret_cast<internal::GenericFunction>(&internal::Invoker<ReturnType, Args...>::invoke), - reinterpret_cast<internal::GenericFunction>(fn)); + reinterpret_cast<GenericFunction>(&Invoker<ReturnType, Args...>::invoke), + reinterpret_cast<GenericFunction>(fn)); } namespace internal { template<typename ClassType, typename... Args> + ClassType* operator_new(Args... args) { + return new ClassType(args...); + } + + template<typename WrapperType, typename ClassType, typename... Args> + WrapperType wrapped_new(Args... args) { + return WrapperType(new ClassType(args...)); + } + + template<typename ClassType, typename... Args> ClassType* raw_constructor( typename internal::BindingType<Args>::WireType... args ) { @@ -215,302 +295,812 @@ namespace emscripten { delete ptr; } - template<typename ClassType, typename ReturnType, typename... Args> - struct MethodInvoker { - typedef ReturnType (ClassType::*MemberPointer)(Args...); + template<typename FunctionPointerType, typename ReturnType, typename ThisType, typename... Args> + struct FunctionInvoker { static typename internal::BindingType<ReturnType>::WireType invoke( - ClassType* ptr, - const MemberPointer& method, + FunctionPointerType* function, + typename internal::BindingType<ThisType>::WireType wireThis, typename internal::BindingType<Args>::WireType... args ) { return internal::BindingType<ReturnType>::toWireType( - (ptr->*method)( - internal::BindingType<Args>::fromWireType(args)... - ) + (*function)( + internal::BindingType<ThisType>::fromWireType(wireThis), + internal::BindingType<Args>::fromWireType(args)...) ); } }; - template<typename ClassType, typename... Args> - struct MethodInvoker<ClassType, void, Args...> { - typedef void (ClassType::*MemberPointer)(Args...); + template<typename FunctionPointerType, typename ThisType, typename... Args> + struct FunctionInvoker<FunctionPointerType, void, ThisType, Args...> { static void invoke( - ClassType* ptr, - const MemberPointer& method, + FunctionPointerType* function, + typename internal::BindingType<ThisType>::WireType wireThis, typename internal::BindingType<Args>::WireType... args ) { - return (ptr->*method)( - internal::BindingType<Args>::fromWireType(args)... - ); + (*function)( + internal::BindingType<ThisType>::fromWireType(wireThis), + internal::BindingType<Args>::fromWireType(args)...); } }; - template<typename ClassType, typename ReturnType, typename... Args> - struct ConstMethodInvoker { - typedef ReturnType (ClassType::*MemberPointer)(Args...) const; + template<typename MemberPointer, + typename ReturnType, + typename ThisType, + typename... Args> + struct MethodInvoker { static typename internal::BindingType<ReturnType>::WireType invoke( - const ClassType* ptr, const MemberPointer& method, + typename internal::BindingType<ThisType>::WireType wireThis, typename internal::BindingType<Args>::WireType... args ) { return internal::BindingType<ReturnType>::toWireType( - (ptr->*method)( + (internal::BindingType<ThisType>::fromWireType(wireThis)->*method)( internal::BindingType<Args>::fromWireType(args)... ) ); } }; - template<typename ClassType, typename... Args> - struct ConstMethodInvoker<ClassType, void, Args...> { - typedef void (ClassType::*MemberPointer)(Args...) const; + template<typename MemberPointer, + typename ThisType, + typename... Args> + struct MethodInvoker<MemberPointer, void, ThisType, Args...> { static void invoke( - const ClassType* ptr, const MemberPointer& method, + typename internal::BindingType<ThisType>::WireType wireThis, typename internal::BindingType<Args>::WireType... args ) { - return (ptr->*method)( + return (internal::BindingType<ThisType>::fromWireType(wireThis)->*method)( internal::BindingType<Args>::fromWireType(args)... ); } }; - template<typename ClassType, typename FieldType> - struct FieldAccess { - typedef FieldType ClassType::*MemberPointer; - typedef internal::BindingType<FieldType> FieldBinding; - typedef typename FieldBinding::WireType WireType; + template<typename InstanceType, typename MemberType> + struct MemberAccess { + typedef MemberType InstanceType::*MemberPointer; + typedef internal::BindingType<MemberType> MemberBinding; + typedef typename MemberBinding::WireType WireType; - static WireType get( - ClassType& ptr, - const MemberPointer& field + template<typename ClassType> + static WireType getWire( + const MemberPointer& field, + const ClassType& ptr ) { - return FieldBinding::toWireType(ptr.*field); + return MemberBinding::toWireType(ptr.*field); } - static void set( - ClassType& ptr, + template<typename ClassType> + static void setWire( const MemberPointer& field, + ClassType& ptr, WireType value ) { - ptr.*field = FieldBinding::fromWireType(value); + ptr.*field = MemberBinding::fromWireType(value); } + }; - template<typename Getter> - static WireType propertyGet( - ClassType& ptr, - const Getter& getter - ) { - return FieldBinding::toWireType(getter(ptr)); + // TODO: This could do a reinterpret-cast if sizeof(T) === sizeof(void*) + template<typename T> + inline void* getContext(const T& t) { + // not a leak because this is called once per binding + void* p = malloc(sizeof(T)); + assert(p); + memcpy(p, &t, sizeof(T)); + return p; + } + + 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)()); } - template<typename Setter> - static void propertySet( - ClassType& ptr, - const Setter& setter, - WireType value - ) { - setter(ptr, FieldBinding::fromWireType(value)); + 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_tuple { + class value_tuple : public internal::noncopyable { public: value_tuple(const char* name) { - internal::registerStandardTypes(); - internal::_embind_register_tuple( - internal::getTypeID<ClassType>(), + using namespace internal; + _embind_register_tuple( + TypeID<ClassType>::get(), name, - reinterpret_cast<internal::GenericFunction>(&internal::raw_constructor<ClassType>), - reinterpret_cast<internal::GenericFunction>(&internal::raw_destructor<ClassType>)); - } - - template<typename ElementType> - value_tuple& element(ElementType ClassType::*field) { - internal::_embind_register_tuple_element( - internal::getTypeID<ClassType>(), - internal::getTypeID<ElementType>(), - reinterpret_cast<internal::GenericFunction>(&internal::FieldAccess<ClassType, ElementType>::get), - reinterpret_cast<internal::GenericFunction>(&internal::FieldAccess<ClassType, ElementType>::set), - sizeof(field), - &field); - - return *this; + reinterpret_cast<GenericFunction>(&raw_constructor<ClassType>), + reinterpret_cast<GenericFunction>(&raw_destructor<ClassType>)); } - template<typename ElementType> - value_tuple& element(ElementType (*getter)(const ClassType&), void (*setter)(ClassType&, ElementType)) { - internal::_embind_register_tuple_element_accessor( - internal::getTypeID<ClassType>(), - internal::getTypeID<ElementType>(), - reinterpret_cast<internal::GenericFunction>(&internal::FieldAccess<ClassType, ElementType>::template propertyGet<ElementType(const ClassType&)>), - sizeof(getter), - &getter, - reinterpret_cast<internal::GenericFunction>(&internal::FieldAccess<ClassType, ElementType>::template propertySet<void(ClassType&, ElementType)>), - sizeof(setter), - &setter); - return *this; + ~value_tuple() { + using namespace internal; + _embind_finalize_tuple(TypeID<ClassType>::get()); } - template<typename ElementType> - value_tuple& element(ElementType (*getter)(const ClassType&), void (*setter)(ClassType&, const ElementType&)) { - internal::_embind_register_tuple_element_accessor( - internal::getTypeID<ClassType>(), - internal::getTypeID<ElementType>(), - reinterpret_cast<internal::GenericFunction>(&internal::FieldAccess<ClassType, ElementType>::template propertyGet<ElementType(const ClassType&)>), - sizeof(getter), - &getter, - reinterpret_cast<internal::GenericFunction>(&internal::FieldAccess<ClassType, ElementType>::template propertySet<void(ClassType&, ElementType)>), - sizeof(setter), - &setter); + template<typename InstanceType, typename ElementType> + value_tuple& element(ElementType InstanceType::*field) { + using namespace internal; + _embind_register_tuple_element( + TypeID<ClassType>::get(), + TypeID<ElementType>::get(), + reinterpret_cast<GenericFunction>( + &MemberAccess<InstanceType, ElementType> + ::template getWire<ClassType>), + getContext(field), + TypeID<ElementType>::get(), + reinterpret_cast<GenericFunction>( + &MemberAccess<InstanceType, ElementType> + ::template setWire<ClassType>), + getContext(field)); return *this; } - template<typename ElementType> - value_tuple& element(ElementType (*getter)(const ClassType&), void (*setter)(ClassType&, const ElementType&&)) { - internal::_embind_register_tuple_element_accessor( - internal::getTypeID<ClassType>(), - internal::getTypeID<ElementType>(), - reinterpret_cast<internal::GenericFunction>(&internal::FieldAccess<ClassType, ElementType>::template propertyGet<ElementType(const ClassType&)>), - sizeof(getter), - &getter, - reinterpret_cast<internal::GenericFunction>(&internal::FieldAccess<ClassType, ElementType>::template propertySet<void(ClassType&, ElementType)>), - sizeof(setter), - &setter); + template<typename Getter, typename Setter> + value_tuple& element(Getter getter, Setter setter) { + using namespace internal; + typedef GetterPolicy<Getter> GP; + typedef SetterPolicy<Setter> SP; + _embind_register_tuple_element( + TypeID<ClassType>::get(), + 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 ElementType> - value_tuple& element(ElementType (*getter)(const ClassType&), void (*setter)(ClassType&, ElementType&)) { - internal::_embind_register_tuple_element_accessor( - internal::getTypeID<ClassType>(), - internal::getTypeID<ElementType>(), - reinterpret_cast<internal::GenericFunction>(&internal::FieldAccess<ClassType, ElementType>::template propertyGet<ElementType(const ClassType&)>), - sizeof(getter), - &getter, - reinterpret_cast<internal::GenericFunction>(&internal::FieldAccess<ClassType, ElementType>::template propertySet<void(ClassType&, ElementType)>), - sizeof(setter), - &setter); + template<int Index> + value_tuple& element(index<Index>) { + using namespace internal; + ClassType* null = 0; + typedef typename std::remove_reference<decltype((*null)[Index])>::type ElementType; + _embind_register_tuple_element( + TypeID<ClassType>::get(), + TypeID<ElementType>::get(), + reinterpret_cast<GenericFunction>(&internal::get_by_index<ClassType, ElementType>), + reinterpret_cast<void*>(Index), + TypeID<ElementType>::get(), + reinterpret_cast<GenericFunction>(&internal::set_by_index<ClassType, ElementType>), + reinterpret_cast<void*>(Index)); return *this; } }; + //////////////////////////////////////////////////////////////////////////////// + // VALUE STRUCTS + //////////////////////////////////////////////////////////////////////////////// + template<typename ClassType> - class value_struct { + class value_struct : public internal::noncopyable { public: value_struct(const char* name) { - internal::registerStandardTypes(); - internal::_embind_register_struct( - internal::getTypeID<ClassType>(), + using namespace internal; + _embind_register_struct( + TypeID<ClassType>::get(), name, - reinterpret_cast<internal::GenericFunction>(&internal::raw_constructor<ClassType>), - reinterpret_cast<internal::GenericFunction>(&internal::raw_destructor<ClassType>)); + reinterpret_cast<GenericFunction>(&raw_constructor<ClassType>), + reinterpret_cast<GenericFunction>(&raw_destructor<ClassType>)); } - template<typename FieldType> - value_struct& field(const char* fieldName, FieldType ClassType::*field) { - internal::_embind_register_struct_field( - internal::getTypeID<ClassType>(), + ~value_struct() { + _embind_finalize_struct(internal::TypeID<ClassType>::get()); + } + + template<typename InstanceType, typename FieldType> + value_struct& field(const char* fieldName, FieldType InstanceType::*field) { + using namespace internal; + _embind_register_struct_field( + TypeID<ClassType>::get(), fieldName, - internal::getTypeID<FieldType>(), - reinterpret_cast<internal::GenericFunction>(&internal::FieldAccess<ClassType, FieldType>::get), - reinterpret_cast<internal::GenericFunction>(&internal::FieldAccess<ClassType, FieldType>::set), - sizeof(field), - &field); - + TypeID<FieldType>::get(), + reinterpret_cast<GenericFunction>( + &MemberAccess<InstanceType, FieldType> + ::template getWire<ClassType>), + getContext(field), + TypeID<FieldType>::get(), + reinterpret_cast<GenericFunction>( + &MemberAccess<InstanceType, FieldType> + ::template setWire<ClassType>), + getContext(field)); + return *this; + } + + template<typename Getter, typename Setter> + value_struct& field( + const char* fieldName, + Getter getter, + Setter setter + ) { + using namespace internal; + typedef GetterPolicy<Getter> GP; + typedef SetterPolicy<Setter> SP; + _embind_register_struct_field( + 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<int Index> + value_struct& field(const char* fieldName, index<Index>) { + using namespace internal; + ClassType* null = 0; + typedef typename std::remove_reference<decltype((*null)[Index])>::type ElementType; + _embind_register_struct_field( + TypeID<ClassType>::get(), + fieldName, + TypeID<ElementType>::get(), + reinterpret_cast<GenericFunction>(&internal::get_by_index<ClassType, ElementType>), + reinterpret_cast<void*>(Index), + TypeID<ElementType>::get(), + reinterpret_cast<GenericFunction>(&internal::set_by_index<ClassType, ElementType>), + reinterpret_cast<void*>(Index)); return *this; } }; - // TODO: support class definitions without constructors. - // TODO: support external class constructors - template<typename ClassType> + //////////////////////////////////////////////////////////////////////////////// + // 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 + } + }; + + // 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))); + } + + 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 + //////////////////////////////////////////////////////////////////////////////// + + // abstract classes + template<typename T> |