diff options
author | Bill Welden <bwelden@BWELDEN-T1600.corp.imvu.com> | 2012-11-10 13:01:34 -0800 |
---|---|---|
committer | Jukka Jylänki <jujjyl@gmail.com> | 2013-04-12 14:21:57 +0300 |
commit | 338d59e81e5467df7021ad0854cee83b043c1204 (patch) | |
tree | e7c2ea46108fecaaef1077f89c6315049bc900ec | |
parent | 61b2ff66ffe1aba9550c828d5df9ecc0d3af8f7b (diff) |
More files for upcast/downcast commit.
-rwxr-xr-x[-rw-r--r--] | src/embind/embind.js | 61 | ||||
-rwxr-xr-x[-rw-r--r--] | system/include/emscripten/bind.h | 74 |
2 files changed, 123 insertions, 12 deletions
diff --git a/src/embind/embind.js b/src/embind/embind.js index 6a59f11d..f491c1dd 100644..100755 --- a/src/embind/embind.js +++ b/src/embind/embind.js @@ -413,6 +413,7 @@ function __embind_register_smart_ptr( registerType(pointerType, name, { name: name, + Handle: Handle, fromWireType: function(ptr) { if (!getPointee(ptr)) { destructor(ptr); @@ -541,7 +542,7 @@ function __embind_register_class( return body.apply(this, arguments); }); constructor.prototype = Handle.prototype; - + registerType(classType, name, { name: name, constructor: constructor, @@ -643,6 +644,64 @@ function __embind_register_class_method( }; } +function __embind_register_cast_method( + classType, + methodName, + returnType, + invoker +) { + classType = requireRegisteredType(classType, 'class'); + methodName = Pointer_stringify(methodName); + var humanName = classType.name + '.' + methodName; + + returnType = requireRegisteredType(returnType, 'method ' + humanName + ' return value'); + invoker = FUNCTION_TABLE[invoker]; + + classType.Handle.prototype[methodName] = function() { + if (!this.ptr) { + throw new BindingError('cannot call emscripten binding method ' + humanName + ' on deleted object'); + } + if (arguments.length !== 0) { + throw new BindingError('emscripten binding method ' + humanName + ' called with arguments, none expected'); + } + + var args = new Array(1); + args[0] = this.ptr; + var rv = returnType.fromWireType(invoker.apply(null, args)); // in case ptr needs to be adjusted for multiple inheritance + return rv; + }; +} + +function __embind_register_pointer_cast_method( + classType, + methodName, + returnType, + invoker +) { + classType = requireRegisteredType(classType, 'class'); + methodName = Pointer_stringify(methodName); + var humanName = classType.name + '.' + methodName; + + returnType = requireRegisteredType(returnType, 'method ' + humanName + ' return value'); + invoker = FUNCTION_TABLE[invoker]; + + classType.Handle.prototype[methodName] = function() { + if (!this.ptr) { + throw new BindingError('cannot call emscripten binding method ' + humanName + ' on deleted object'); + } + if (arguments.length !== 0) { + throw new BindingError('emscripten binding method ' + humanName + ' called with arguments, none expected'); + } + var args = new Array(2); + var newPtr = _malloc(8); + args[0] = newPtr; + args[1] = this.smartPointer; + invoker.apply(null,args); + var rv = returnType.fromWireType(newPtr); // in case ptr needs to be adjusted for multiple inheritance + return rv; + }; +} + function __embind_register_class_classmethod( classType, methodName, diff --git a/system/include/emscripten/bind.h b/system/include/emscripten/bind.h index e20a5e68..ec3db2d2 100644..100755 --- a/system/include/emscripten/bind.h +++ b/system/include/emscripten/bind.h @@ -133,6 +133,18 @@ namespace emscripten { size_t memberFunctionSize, void* memberFunction); + void _embind_register_cast_method( + TYPEID classType, + const char* methodName, + TYPEID returnType, + GenericFunction invoker); + + void _embind_register_pointer_cast_method( + TYPEID classType, + const char* methodName, + TYPEID returnType, + GenericFunction invoker); + void _embind_register_class_field( TYPEID classType, const char* fieldName, @@ -253,6 +265,17 @@ namespace emscripten { // FUNCTIONS //////////////////////////////////////////////////////////////////////////////// + + template<typename FromType, typename ToType> + ToType& performCast(FromType& from) { + return *dynamic_cast<ToType*>(&from); + }; + + template<typename FromRawType, typename ToRawType> + std::shared_ptr<ToRawType> performPointerCast(std::shared_ptr<FromRawType> from) { + return std::shared_ptr<ToRawType>(from, dynamic_cast<ToRawType*>(from.get())); + }; + template<typename ReturnType, typename... Args, typename... Policies> void function(const char* name, ReturnType (fn)(Args...), Policies...) { using namespace internal; @@ -563,17 +586,35 @@ namespace emscripten { //////////////////////////////////////////////////////////////////////////////// template<typename PointerType> - inline void register_smart_ptr(const char* name) { - typedef typename PointerType::element_type PointeeType; + class register_smart_ptr { + public: + register_smart_ptr(const char* name) { + using namespace internal; + typedef typename PointerType::element_type PointeeType; - internal::registerStandardTypes(); - internal::_embind_register_smart_ptr( - internal::TypeID<PointerType>::get(), - internal::TypeID<PointeeType>::get(), - name, - reinterpret_cast<internal::GenericFunction>(&internal::raw_destructor<PointerType>), - reinterpret_cast<internal::GenericFunction>(&internal::get_pointee<PointerType>)); - } + registerStandardTypes(); + _embind_register_smart_ptr( + TypeID<PointerType>::get(), + TypeID<PointeeType>::get(), + name, + reinterpret_cast<GenericFunction>(&raw_destructor<PointerType>), + reinterpret_cast<GenericFunction>(&get_pointee<PointerType>)); + + } + + template<typename ReturnType> + register_smart_ptr& cast(const char* methodName) { + using namespace internal; + typedef typename ReturnType::element_type ReturnPointeeType; + typedef typename PointerType::element_type PointeeType; + _embind_register_pointer_cast_method( + TypeID<PointerType>::get(), + methodName, + TypeID<ReturnType>::get(), + reinterpret_cast<GenericFunction>(&performPointerCast<PointeeType,ReturnPointeeType>)); + return *this; + } + }; //////////////////////////////////////////////////////////////////////////////// // VECTORS @@ -599,7 +640,6 @@ namespace emscripten { //////////////////////////////////////////////////////////////////////////////// // CLASSES //////////////////////////////////////////////////////////////////////////////// - // TODO: support class definitions without constructors. // TODO: support external class constructors template<typename ClassType> @@ -708,6 +748,18 @@ namespace emscripten { reinterpret_cast<internal::GenericFunction>(&internal::FunctorInvoker<ClassType, ReturnType, Args...>::invoke)); return *this; } + + template<typename ReturnType> + class_& cast(const char* methodName) { + using namespace internal; + + _embind_register_cast_method( + TypeID<ClassType>::get(), + methodName, + TypeID<ReturnType>::get(), + reinterpret_cast<GenericFunction>(&performCast<ClassType,ReturnType>)); + return *this; + } }; //////////////////////////////////////////////////////////////////////////////// |