aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Welden <bwelden@imvu.com>2013-01-28 14:03:27 -0800
committerJukka Jylänki <jujjyl@gmail.com>2013-04-12 14:23:41 +0300
commit40ad51a5c81881ae0ddb5c36f19e7d362107ccc6 (patch)
tree0c8763dcc4d5eb5610ef71e423398039d886cb78
parentec5bc68515751aae5e90eb9a55af1908b2cb8329 (diff)
Revert "register_smart_ptr changed to .shared_ptr (mod to class definition) -- shared_ptr (outside of class definition) is still allowed"
This reverts commit c38bb38e9d6393dfacb4afb0e9ba80ce42aee965.
-rwxr-xr-xsrc/embind/embind.js155
-rwxr-xr-xsystem/include/emscripten/bind.h62
-rwxr-xr-xsystem/lib/embind/bind.cpp20
3 files changed, 133 insertions, 104 deletions
diff --git a/src/embind/embind.js b/src/embind/embind.js
index 7210dbc1..d8a4a440 100755
--- a/src/embind/embind.js
+++ b/src/embind/embind.js
@@ -5,6 +5,7 @@
/*global Pointer_stringify, writeStringToMemory*/
/*global __emval_register, _emval_handle_array, __emval_decref*/
/*global ___getDynamicPointerType: false*/
+/*global ___dynamicPointerCast: false*/
/*global ___typeName:false*/
/*global ___staticPointerCast: false*/
@@ -307,12 +308,6 @@ function runDestructors(destructors) {
}
}
-function refreshSmartPointee(handle) {
- if (handle && handle.smartPointer) {
- handle.ptr = handle.type.smartPointerType.getPointee(handle.smartPointer);
- }
-}
-
function makeInvoker(name, argCount, argTypes, invoker, fn) {
if (!FUNCTION_TABLE[fn]) {
throw new BindingError('function '+name+' is not defined');
@@ -334,9 +329,6 @@ function makeInvoker(name, argCount, argTypes, invoker, fn) {
rv = argTypes[0].fromWireType(rv);
}
runDestructors(destructors);
- for (i = 1; i < argCount; i++) {
- refreshSmartPointee(arguments[i-1]);
- }
return rv;
};
}
@@ -545,21 +537,21 @@ RegisteredPointer.prototype.toWireType = function(destructors, handle) {
if (!handle) {
return null;
}
- if (handle.type.isPolymorphic) {
- fromRawType = handle.type.getDynamicRawPointerType(handle.ptr);
+ if (handle.pointeeType.isPolymorphic) {
+ fromRawType = handle.pointeeType.getDynamicRawPointerType(handle.ptr);
} else {
- fromRawType = handle.type.rawType;
+ fromRawType = handle.pointeeType.rawType;
}
- if (fromRawType === this.type.rawType) {
+ if (fromRawType === this.pointeeType.rawType) {
return this.isSmartPointer ? handle.smartPointer : handle.ptr;
}
- var ptr = staticPointerCast(handle.ptr, fromRawType, this.type.rawType);
+ var ptr = staticPointerCast(handle.ptr, fromRawType, this.pointeeType.rawType);
if (this.isSmartPointer) {
// todo: if ptr == handle.ptr, there's no need to allocate a new smartPtr!
- var smartPtr = _malloc(16); // todo: can we get C++ to tell us the size of the pointer?
- handle.type.smartPointerType.rawConstructor(smartPtr, ptr, handle.smartPointer);
+ var smartPtr = _malloc(16);
+ handle.pointeeType.smartPointerType.rawConstructor(smartPtr, ptr, handle.smartPointer);
ptr = smartPtr;
- destructors.push(handle.type.smartPointerType.rawDestructor);
+ destructors.push(handle.pointeeType.smartPointerType.rawDestructor);
destructors.push(ptr);
}
return ptr;
@@ -590,7 +582,7 @@ RegisteredPointer.prototype.fromWireType = function(ptr) {
RegisteredPointer.prototype.getDynamicRawPointerType = function(ptr) {
var type = null;
if (this.isPolymorphic) {
- if (this.rawGetPointee) { // todo: did you mean isSmartPtr?
+ if (this.rawGetPointee) {
type = ___getDynamicPointerType(this.rawGetPointee(ptr));
} else {
type = ___getDynamicPointerType(ptr);
@@ -602,8 +594,8 @@ RegisteredPointer.prototype.getDynamicRawPointerType = function(ptr) {
RegisteredPointer.prototype.getDynamicDowncastType = function(ptr) {
var downcastType = null;
var type = this.getDynamicRawPointerType(ptr);
- if (type && type !== this.type.rawType) {
- var derivation = Module.__getDerivationPath(type, this.type.rawType);
+ if (type && type !== this.pointeeType.rawType) {
+ var derivation = Module.__getDerivationPath(type, this.pointeeType.rawType);
for (var i = 0; i < derivation.size(); i++) {
downcastType = typeRegistry[derivation.at(i)];
if (downcastType) {
@@ -623,7 +615,7 @@ RegisteredPointer.prototype.fromWireTypeAutoDowncast = function(ptr) { // ptr is
}
var toType = this.getDynamicDowncastType(ptr);
if (toType) {
- var fromType = this.type;
+ var fromType = this.pointeeType;
if (this.isSmartPointer) {
handle = toType.smartPointerType.fromWireType(ptr);
} else {
@@ -649,16 +641,12 @@ function __embind_register_smart_ptr(
rawConstructor = FUNCTION_TABLE[rawConstructor];
rawDestructor = FUNCTION_TABLE[rawDestructor];
rawGetPointee = FUNCTION_TABLE[rawGetPointee];
-
- if (name == "") {
- name = pointeeType.name + "Ptr";
- }
-
+
var Handle = createNamedFunction(name, function(ptr) {
this.count = {value: 1};
this.smartPointer = ptr; // std::shared_ptr<T>*
this.ptr = rawGetPointee(ptr); // T*
- this.type = pointeeType;
+ this.pointeeType = pointeeType;
});
// TODO: test for SmartPtr.prototype.constructor property?
@@ -692,7 +680,7 @@ function __embind_register_smart_ptr(
this.ptr = undefined;
};
var registeredPointer = new RegisteredPointer(Handle, pointeeType.isPolymorphic, true, rawGetPointee, rawConstructor, rawDestructor);
- registeredPointer.type = pointeeType;
+ registeredPointer.pointeeType = pointeeType;
pointeeType.smartPointerType = registerType(rawType, name, registeredPointer);
}
@@ -840,13 +828,11 @@ function __embind_register_class(
h.count = {value: 1, ptr: ptr };
h.ptr = ptr;
- h.type = type; // set below
+ h.pointeeType = type; // set below
for(var prop in Handle.prototype) {
- if (Handle.prototype.hasOwnProperty(prop)) {
- var dp = Object.getOwnPropertyDescriptor(Handle.prototype, prop);
- Object.defineProperty(h, prop, dp);
- }
+ var dp = Object.getOwnPropertyDescriptor(Handle.prototype, prop);
+ Object.defineProperty(h, prop, dp);
}
return h;
@@ -889,15 +875,15 @@ function __embind_register_class(
// todo: clean this up!
var registeredClass = new RegisteredPointer(Handle, isPolymorphic, false);
var type = registerType(rawType, name, registeredClass);
- registeredClass.type = type;
+ registeredClass.pointeeType = type;
- registeredClass = new RegisteredPointer(Handle, isPolymorphic, false);
+ var registeredClass = new RegisteredPointer(Handle, isPolymorphic, false);
registerType(rawPointerType, name + '*', registeredClass);
- registeredClass.type = type;
+ registeredClass.pointeeType = type;
// todo: implement const pointers (no modification Javascript side)
- registeredClass = new RegisteredPointer(Handle, isPolymorphic, false);
+ var registeredClass = new RegisteredPointer(Handle, isPolymorphic, false);
registerType(rawConstPointerType, name + ' const*', registeredClass);
- registeredClass.type = type;
+ registeredClass.pointeeType = type;
type.constructor = createNamedFunction(type.name, function() {
var body = type.constructor.body;
@@ -979,32 +965,26 @@ function __embind_register_class_method(
rv = argTypes[0].fromWireType(rv);
}
runDestructors(destructors);
- for (i = 1; i < argCount; i++) {
- refreshSmartPointee(arguments[i-1]);
- }
return rv;
};
classType.Handle.memberType[methodName] = "method";
});
}
-function __embind_register_cast_method(
+// todo: cast methods should require binding of their target types
+function __embind_register_raw_cast_method(
rawClassType,
isPolymorphic,
methodName,
- rawRawReturnType,
- rawSharedReturnType,
- rawRawCaster,
- rawSharedCaster
+ rawReturnType,
+ rawInvoker
) {
requestDeferredRegistration(function() {
var classType = requireRegisteredType(rawClassType, 'class');
methodName = Pointer_stringify(methodName);
var humanName = classType.name + '.' + methodName;
- var rawReturnType = requireRegisteredType(rawRawReturnType, 'method ' + humanName + ' return value');
- var sharedReturnType = requireRegisteredType(rawSharedReturnType, 'method ' + humanName + ' shared pointer return value');
- var rawCaster = FUNCTION_TABLE[rawRawCaster];
- var sharedCaster = FUNCTION_TABLE[rawSharedCaster];
+ var returnType = requireRegisteredType(rawReturnType, 'method ' + humanName + ' return value');
+ rawInvoker = FUNCTION_TABLE[rawInvoker];
classType.Handle.prototype[methodName] = function() {
if (!this.ptr) {
throw new BindingError('cannot call emscripten binding method ' + humanName + ' on deleted object');
@@ -1015,11 +995,11 @@ function __embind_register_cast_method(
if (isPolymorphic) {
// todo: this is all only to validate the cast -- cache the result
var runtimeType = ___getDynamicPointerType(this.ptr);
- var derivation = Module.__getDerivationPath(rawRawReturnType, runtimeType); // downcast is valid
+ var derivation = Module.__getDerivationPath(rawReturnType, runtimeType); // downcast is valid
var size = derivation.size();
derivation.delete();
if (size === 0) {
- derivation = Module.__getDerivationPath(runtimeType, rawRawReturnType); // upcast is valid
+ derivation = Module.__getDerivationPath(runtimeType, rawReturnType); // upcast is valid
size = derivation.size();
derivation.delete();
if (size === 0) {
@@ -1027,29 +1007,64 @@ function __embind_register_cast_method(
}
}
}
- var args;
- var ptr;
- var rv;
- if (this.smartPointer) {
- args = new Array(2);
- ptr = _malloc(8);
- args[0] = ptr;
- args[1] = this.smartPointer;
- sharedCaster.apply(null,args); // need a smart pointer raw invoker
- rv = sharedReturnType.fromWireType(ptr);
- } else {
- args = new Array(1);
- args[0] = this.ptr;
- ptr = rawCaster.apply(null, args);
- rv = rawReturnType.fromWireType(ptr);
- rv.count = this.count;
- this.count.value ++;
- }
+ var args = new Array(1);
+ args[0] = this.ptr;
+ var ptr = rawInvoker.apply(null, args);
+ var rv = returnType.fromWireType(ptr);
+ rv.count = this.count;
+ this.count.value ++;
return rv;
};
});
}
+// todo: cast methods should not be passed from the smart ptr to the contained object!!
+function __embind_register_smart_cast_method(
+ rawPointerType,
+ rawReturnType,
+ returnPointeeType,
+ isPolymorphic,
+ methodName,
+ rawInvoker
+) {
+ requestDeferredRegistration(function() {
+ var pointerType = requireRegisteredType(rawPointerType, 'smart pointer class');
+ methodName = Pointer_stringify(methodName);
+ var humanName = pointerType.name + '.' + methodName;
+ var returnType = requireRegisteredType(rawReturnType, 'method ' + humanName + ' return value');
+ rawInvoker = FUNCTION_TABLE[rawInvoker];
+ pointerType.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');
+ }
+ if (isPolymorphic) {
+ // todo: just validating the cast -- cache the result
+ var runtimeType = ___getDynamicPointerType(this.ptr);
+ var derivation = Module.__getDerivationPath(returnPointeeType, runtimeType); // downcast is valid
+ var size = derivation.size();
+ derivation.delete();
+ if (size === 0) {
+ derivation = Module.__getDerivationPath(runtimeType, returnPointeeType); // upcast is valid
+ size = derivation.size();
+ derivation.delete();
+ if (size === 0) {
+ throw new CastError("Pointer conversion is not available");
+ }
+ }
+ }
+ var args = new Array(2);
+ var ptr = _malloc(8);
+ args[0] = ptr;
+ args[1] = this.smartPointer;
+ rawInvoker.apply(null,args);
+ return returnType.fromWireType(ptr);
+ };
+ });
+}
+
function __embind_register_class_classmethod(
rawClassType,
methodName,
diff --git a/system/include/emscripten/bind.h b/system/include/emscripten/bind.h
index a3789cab..ce9053f2 100755
--- a/system/include/emscripten/bind.h
+++ b/system/include/emscripten/bind.h
@@ -124,14 +124,20 @@ namespace emscripten {
size_t memberFunctionSize,
void* memberFunction);
- void _embind_register_cast_method(
+ void _embind_register_raw_cast_method(
TYPEID classType,
bool isPolymorphic,
const char* methodName,
TYPEID returnType,
- TYPEID sharedReturnType,
- GenericFunction rawInvoker,
- GenericFunction sharedInvoker);
+ GenericFunction invoker);
+
+ void _embind_register_smart_cast_method(
+ TYPEID pointerType,
+ TYPEID returnType,
+ TYPEID returnPointeeType,
+ bool isPolymorphic,
+ const char* methodName,
+ GenericFunction invoker);
void _embind_register_class_field(
TYPEID classType,
@@ -268,6 +274,7 @@ namespace emscripten {
extern "C" {
int __getDynamicPointerType(int p);
+ int __dynamicPointerCast(int p, int to);
}
template<typename FromType, typename ToType>
@@ -276,14 +283,14 @@ namespace emscripten {
};
template<typename FromRawType, typename ToRawType, bool isPolymorphic>
- struct performSharedCast {
+ struct performShared {
static std::shared_ptr<ToRawType> cast(std::shared_ptr<FromRawType> from) {
return std::dynamic_pointer_cast<ToRawType>(from);
};
};
template<typename FromRawType, typename ToRawType>
- struct performSharedCast<FromRawType, ToRawType, false> {
+ struct performShared<FromRawType, ToRawType, false> {
static std::shared_ptr<ToRawType> cast(std::shared_ptr<FromRawType> from) {
return std::shared_ptr<ToRawType>(from, static_cast<ToRawType*>(from.get()));
};
@@ -293,7 +300,7 @@ namespace emscripten {
void function(const char* name, ReturnType (fn)(Args...), Policies...) {
using namespace internal;
- registerStandardTypes(); // todo: remove all
+ registerStandardTypes();
typename WithPolicies<Policies...>::template ArgTypeList<ReturnType, Args...> args;
_embind_register_function(
@@ -618,12 +625,21 @@ namespace emscripten {
reinterpret_cast<GenericFunction>(&get_pointee<PointerType>));
}
- };
- template<typename PointeeType>
- class shared_ptr: public register_smart_ptr<std::shared_ptr<PointeeType>> {
- public:
- shared_ptr(const char* name): register_smart_ptr<std::shared_ptr<PointeeType>>(name) {};
+ 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_smart_cast_method(
+ TypeID<PointerType>::get(),
+ TypeID<ReturnType>::get(),
+ TypeID<ReturnPointeeType>::get(),
+ std::is_polymorphic<PointeeType>::value,
+ methodName,
+ reinterpret_cast<GenericFunction>(&performShared<PointeeType, ReturnPointeeType, std::is_polymorphic<PointeeType>::value>::cast));
+ return *this;
+ }
};
////////////////////////////////////////////////////////////////////////////////
@@ -761,31 +777,13 @@ namespace emscripten {
template<typename ReturnType>
class_& cast(const char* methodName) {
using namespace internal;
- //typedef typename std::shared_ptr<ClassType> PointerType;
- typedef typename std::shared_ptr<ReturnType> SharedReturnType;
- _embind_register_cast_method(
+ _embind_register_raw_cast_method(
TypeID<ClassType>::get(),
std::is_polymorphic<ClassType>::value,
methodName,
TypeID<ReturnType>::get(),
- TypeID<SharedReturnType>::get(),
- reinterpret_cast<GenericFunction>(&performRawStaticCast<ClassType, ReturnType>),
- reinterpret_cast<GenericFunction>(&performSharedCast<ClassType, ReturnType, std::is_polymorphic<ClassType>::value>::cast));
- return *this;
- }
-
- class_& shared_ptr(const char* ptrName = "") {
- using namespace internal;
- typedef typename std::shared_ptr<ClassType> PointerType;
-
- _embind_register_smart_ptr(
- TypeID<PointerType>::get(),
- TypeID<ClassType>::get(),
- ptrName,
- reinterpret_cast<GenericFunction>(&raw_smart_pointer_constructor<ClassType*>),
- reinterpret_cast<GenericFunction>(&raw_destructor<PointerType>),
- reinterpret_cast<GenericFunction>(&get_pointee<PointerType>));
+ reinterpret_cast<GenericFunction>(&performRawStaticCast<ClassType,ReturnType>));
return *this;
}
};
diff --git a/system/lib/embind/bind.cpp b/system/lib/embind/bind.cpp
index bc79876f..5e82bb7e 100755
--- a/system/lib/embind/bind.cpp
+++ b/system/lib/embind/bind.cpp
@@ -101,7 +101,7 @@ namespace emscripten {
// __getDerivationPath returns an array of type_info pointers describing the derivation chain starting with
// the derived type and proceeding toward (and ending with) the base type. Types are only included if they
// appear on all possible derivation paths.
- std::vector<int> __getDerivationPath(int dv, const int bs) { // todo: use emval array to pass return value??
+ std::vector<int> __getDerivationPath(int dv, const int bs) {
std::vector<std::vector<const __cxxabiv1::__class_type_info*>> paths;
const std::type_info* dv1 = (std::type_info*)dv;
@@ -176,11 +176,27 @@ namespace emscripten {
// __getDynamicPointerType returns (for polymorphic types only!) the type of the instance actually
// pointed to.
- int EMSCRIPTEN_KEEPALIVE __getDynamicPointerType(int p) { // use size_t
+ int EMSCRIPTEN_KEEPALIVE __getDynamicPointerType(int p) {
void** vtable = *(void***)p;
return (int)static_cast<const std::type_info*>(vtable[-1]);
}
+ // Calls to __dynamic_cast are generated by the compiler to implement dynamic_cast<>() -- its prototype is
+ // not available through any header file. It is called directly here because it allows run-time
+ // specification of the target pointer type (which can only be specified at compile time when using
+ // dynamic_cast<>().
+ void* __dynamic_cast(void*, const std::type_info*, const std::type_info*, int);
+
+ // __dynamicPointerCast performs a C++ dynamic_cast<>() operation, but allowing run-time specification of
+ // the from and to pointer types.
+ int EMSCRIPTEN_KEEPALIVE __dynamicPointerCast(int p, int to) {
+ int ret = (int)__staticPointerCast((void *)p, __getDynamicPointerType(p), to);
+ if (ret < 0) {
+ return 0;
+ }
+ return ret;
+ }
+
const char* EMSCRIPTEN_KEEPALIVE __typeName(int p) {
const std::type_info* ti = (const std::type_info*)p;
size_t nameLen = std::min(strlen(ti->name()), (unsigned int)1024);