diff options
author | Bill Welden <bwelden@imvu.com> | 2013-01-28 14:03:27 -0800 |
---|---|---|
committer | Jukka Jylänki <jujjyl@gmail.com> | 2013-04-12 14:23:41 +0300 |
commit | 40ad51a5c81881ae0ddb5c36f19e7d362107ccc6 (patch) | |
tree | 0c8763dcc4d5eb5610ef71e423398039d886cb78 | |
parent | ec5bc68515751aae5e90eb9a55af1908b2cb8329 (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-x | src/embind/embind.js | 155 | ||||
-rwxr-xr-x | system/include/emscripten/bind.h | 62 | ||||
-rwxr-xr-x | system/lib/embind/bind.cpp | 20 |
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);
|