diff options
author | mey <mey@imvu.com> | 2012-10-09 17:54:38 -0700 |
---|---|---|
committer | Jukka Jylänki <jujjyl@gmail.com> | 2013-04-12 14:21:14 +0300 |
commit | db4baa7a70f37b6e4754dacf645d8674e52dad43 (patch) | |
tree | ec13ff8dfbd79fe213c38bb182461cc64389e5c2 | |
parent | a20c654c1fcbb877ff8bd0d305f0908695dc8c7e (diff) |
Exposing std::shared_ptr<T> to javascript.
-rw-r--r-- | src/embind/embind.js | 82 | ||||
-rw-r--r-- | system/include/emscripten/bind.h | 26 |
2 files changed, 107 insertions, 1 deletions
diff --git a/src/embind/embind.js b/src/embind/embind.js index d40d6ca2..d9358afd 100644 --- a/src/embind/embind.js +++ b/src/embind/embind.js @@ -354,6 +354,86 @@ function __embind_register_struct_field( }; } +function __embind_register_shared_ptr( + ptrType, + classType, + name, + destructor, + internalPtrGetter +) { + name = Pointer_stringify(name); + classType = requireRegisteredType(classType, 'class'); + destructor = FUNCTION_TABLE[destructor]; + internalPtrGetter = FUNCTION_TABLE[internalPtrGetter]; + + var Handle = createNamedFunction(name, function(ptr) { + this.count = {value: 1}; + this.ptr = ptr; + + var args = new Array(1); + args[0] = ptr; + this.internalReference = classType.fromWireType(internalPtrGetter.apply(null, args)); + }); + + for(var prop in classType.Handle.prototype){ + if(prop === 'clone' || prop === 'move' === prop === 'delete'){ + continue; + } + + function createDuplicatedFunc(prop) { + return function() { + console.log(arguments); + return classType.Handle.prototype[prop].apply(this.internalReference, arguments); + } + } + + Handle.prototype[prop] = createDuplicatedFunc(prop); + } + + Handle.prototype.clone = function() { + if (!this.ptr) { + throw new BindingError(classType.name + ' instance already deleted'); + } + + var clone = Object.create(Handle.prototype); + clone.count = this.count; + clone.ptr = this.ptr; + + clone.count.value += 1; + return clone; + }; + + Handle.prototype.move = function() { + var rv = this.clone(); + this.delete(); + return rv; + }; + + Handle.prototype['delete'] = function() { + if (!this.ptr) { + throw new BindingError(classType.name + ' instance already deleted'); + } + + this.count.value -= 1; + if (0 === this.count.value) { + console.log(destructor); + destructor(this.ptr); + } + this.ptr = undefined; + } + + typeRegistry[ptrType] = { + name: name, + Handle: Handle, + fromWireType: function(ptr) { + return new Handle(ptr); + }, + toWireType: function(destructors, o) { + return o.ptr; + } + }; +} + function __embind_register_class( classType, name, @@ -479,7 +559,7 @@ function __embind_register_class_method( for (var i = 0; i < argCount; ++i) { args[i + 2] = argTypes[i].toWireType(destructors, arguments[i]); } - + var rv = returnType.fromWireType(invoker.apply(null, args)); runDestructors(destructors); return rv; diff --git a/system/include/emscripten/bind.h b/system/include/emscripten/bind.h index 400a9472..2b84878e 100644 --- a/system/include/emscripten/bind.h +++ b/system/include/emscripten/bind.h @@ -91,6 +91,13 @@ namespace emscripten { size_t memberPointerSize, void* memberPointer); + void _embind_register_shared_ptr( + TYPEID ptrType, + TYPEID classType, + const char* ptrName, + GenericFunction destructor, + GenericFunction invoker); + void _embind_register_class( TYPEID classType, const char* className, @@ -215,6 +222,11 @@ namespace emscripten { delete ptr; } + template<typename ClassType> + ClassType* getSharedInternalPtr(std::shared_ptr<ClassType>* ptr) { + return ptr->get(); + } + template<typename ClassType, typename ReturnType, typename... Args> struct MethodInvoker { typedef ReturnType (ClassType::*MemberPointer)(Args...); @@ -424,6 +436,20 @@ namespace emscripten { } }; + template<typename ClassType> + class shared_ptr_ { + public: + shared_ptr_(const char* name) { + internal::registerStandardTypes(); + internal::_embind_register_shared_ptr( + internal::TypeID<std::shared_ptr<ClassType>>::get(), + internal::TypeID<ClassType>::get(), + name, + reinterpret_cast<internal::GenericFunction>(&internal::raw_destructor<std::shared_ptr<ClassType>>), + reinterpret_cast<internal::GenericFunction>(&internal::getSharedInternalPtr<ClassType>)); + } + }; + // TODO: support class definitions without constructors. // TODO: support external class constructors template<typename ClassType> |