Exposing std::shared_ptr<T> to javascript.

This commit is contained in:
mey 2012-10-09 17:54:38 -07:00 коммит произвёл Jukka Jylänki
Родитель a20c654c1f
Коммит db4baa7a70
2 изменённых файлов: 107 добавлений и 1 удалений

Просмотреть файл

@ -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;

Просмотреть файл

@ -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>