summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormey <mey@imvu.com>2012-10-09 17:54:38 -0700
committerJukka Jylänki <jujjyl@gmail.com>2013-04-12 14:21:14 +0300
commitdb4baa7a70f37b6e4754dacf645d8674e52dad43 (patch)
treeec13ff8dfbd79fe213c38bb182461cc64389e5c2
parenta20c654c1fcbb877ff8bd0d305f0908695dc8c7e (diff)
Exposing std::shared_ptr<T> to javascript.
-rw-r--r--src/embind/embind.js82
-rw-r--r--system/include/emscripten/bind.h26
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>