diff options
-rwxr-xr-x | src/embind/embind.js | 33 | ||||
-rwxr-xr-x | system/include/emscripten/bind.h | 2 | ||||
-rwxr-xr-x | system/lib/embind/bind.cpp | 48 |
3 files changed, 56 insertions, 27 deletions
diff --git a/src/embind/embind.js b/src/embind/embind.js index e990c1a1..4ff84005 100755 --- a/src/embind/embind.js +++ b/src/embind/embind.js @@ -497,6 +497,7 @@ function __embind_register_class( classType, pointerType, constPointerType, + isPolymorphic, name, destructor ) { @@ -580,17 +581,31 @@ function __embind_register_class( registerType(pointerType, pointerName, { name: pointerName, fromWireType: function(ptr) { - var dynamicType = ___getDynamicPointerType(ptr); // !!! this won't work if pointer is not dynamic - if (dynamicType === null || dynamicType === pointerType) { - return new Handle(ptr); - } - try { - dynamicType = requireRegisteredType(dynamicType); - } catch (err) { + if (isPolymorphic) { + var toType = ___getDynamicPointerType(ptr); + var toTypeImpl = null; + if (toType === null || toType === pointerType) { + return new Handle(ptr); + } + var derivation = Module.__getDerivationPath(toType, classType); + var candidate = null; + for (var i = 0; i < derivation.size(); i++) { + candidate = derivation.at(i); + toTypeImpl = typeRegistry[candidate]; + if (toTypeImpl) { + break; + } + } + derivation.delete(); + if (toTypeImpl === null) { + return new Handle(ptr); + } + var toTypePointerImpl = requireRegisteredType(toTypeImpl.pointerType); + var castPtr = ___dynamicPointerCast(ptr, classType, candidate); + return toTypePointerImpl.fromWireTypeStatic(castPtr); + } else { return new Handle(ptr); } - dynamicType = requireRegisteredType(dynamicType.pointerType); - return dynamicType.fromWireTypeStatic(ptr); }, fromWireTypeStatic: function(ptr) { return new Handle(ptr); diff --git a/system/include/emscripten/bind.h b/system/include/emscripten/bind.h index 54c017ef..7dc34949 100755 --- a/system/include/emscripten/bind.h +++ b/system/include/emscripten/bind.h @@ -103,6 +103,7 @@ namespace emscripten { TYPEID classType, TYPEID pointerType, TYPEID constPointerType, + bool isPolymorphic, const char* className, GenericFunction destructor); @@ -660,6 +661,7 @@ namespace emscripten { TypeID<ClassType>::get(), TypeID<AllowedRawPointer<ClassType>>::get(), TypeID<AllowedRawPointer<const ClassType>>::get(), + std::is_polymorphic<ClassType>::value, name, reinterpret_cast<GenericFunction>(&raw_destructor<ClassType>)); } diff --git a/system/lib/embind/bind.cpp b/system/lib/embind/bind.cpp index 1fcf987a..9663ad51 100755 --- a/system/lib/embind/bind.cpp +++ b/system/lib/embind/bind.cpp @@ -27,7 +27,7 @@ namespace __cxxabiv1 { return bases;
}
- void __getDerivationPaths1(const __class_type_info* dv, const __class_type_info* bs, std::vector<const __class_type_info*>path, std::vector<std::vector<const __class_type_info*>>& paths) {
+ void __getDerivationPaths(const __class_type_info* dv, const __class_type_info* bs, std::vector<const __class_type_info*>path, std::vector<std::vector<const __class_type_info*>>& paths) {
std::vector<const __class_type_info*> newPath(path);
newPath.emplace_back(dv);
if (dv == bs) {
@@ -35,7 +35,7 @@ namespace __cxxabiv1 { } else {
std::vector<const __class_type_info*> bases = __getBaseClasses(dv);
for (int i = 0; i < bases.size(); i++) {
- __getDerivationPaths1(bases[i], bs, newPath, paths);
+ __getDerivationPaths(bases[i], bs, newPath, paths);
}
}
}
@@ -75,12 +75,10 @@ namespace emscripten { // They are used by embind.js to implement automatic downcasting of return values which are pointers to
// polymorphic objects.
- // __getDerivationPaths returns an array of arrays of type_info pointers (cast as integers to make
- // the Javascript bindings simpler). Each element of the outer array is an array of type_info pointers
- // identifying a derivation path from the derived type to the base type. If either of the type info
- // pointer paramters does not specify a pointer to a class, or if there is no path from the derived type
- // to the base type, this routine returns zero.
- std::vector<std::vector<int>> __getDerivationPaths(int dv, const int bs) {
+ // __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) {
std::vector<std::vector<const __cxxabiv1::__class_type_info*>> paths;
const std::type_info* dv1 = (std::type_info*)dv;
@@ -89,19 +87,33 @@ namespace emscripten { const __cxxabiv1::__class_type_info* bs2 = dynamic_cast<const __cxxabiv1::__class_type_info*>(bs1);
if (dv2 && bs2) {
- __cxxabiv1::__getDerivationPaths1(dv2, bs2, std::vector<const __cxxabiv1::__class_type_info*>(), paths);
+ __cxxabiv1::__getDerivationPaths(dv2, bs2, std::vector<const __cxxabiv1::__class_type_info*>(), paths);
}
- std::vector<std::vector<int>> pathsAsTypeInfo;
- for (int i = 0; i < paths.size(); i++) {
- std::vector<int> pathAsTypeInfo;
- for (int j = 0; j < paths[i].size(); j++) {
- pathAsTypeInfo.emplace_back((int)paths[i][j]);
+ std::vector<int> derivationPath;
+ if (paths.size() > 0) {
+ for (int j = 0; j < paths[0].size(); j++) {
+ bool disqualified = false;
+ for (int i = 1; i < paths.size(); i++) {
+ bool found = false;
+ for (int j2 = 0; j2 < paths[i].size(); j2++) {
+ if (paths[i][j2] == paths[0][j]) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ disqualified = true;
+ break;
+ }
+ }
+ if (!disqualified) {
+ derivationPath.emplace_back((int)paths[0][j]);
+ }
}
- pathsAsTypeInfo.emplace_back(pathAsTypeInfo);
}
- return pathsAsTypeInfo;
+ return derivationPath;
}
// __getDynamicPointerType returns (for polymorphic types only!) the type of the instance actually
@@ -141,10 +153,10 @@ namespace emscripten { }
EMSCRIPTEN_BINDINGS(([]() {
- // We bind __getDerivationPaths in order to take advantage of the std::vector to Javascript array
+ // We bind __getDerivationPath in order to take advantage of the std::vector to Javascript array
// conversion for the return value. This has the unfortunate side-effect of exposing it to third party
// developers, but perhaps the double underscore will scare them away from calling it.
- function("__getDerivationPaths", &__getDerivationPaths);
+ function("__getDerivationPath", &__getDerivationPath);
}));
|