aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xsrc/embind/embind.js136
-rwxr-xr-xsystem/include/emscripten/bind.h12
-rwxr-xr-xsystem/lib/embind/bind.cpp102
3 files changed, 113 insertions, 137 deletions
diff --git a/src/embind/embind.js b/src/embind/embind.js
index 45341700..7f4e0d2e 100755
--- a/src/embind/embind.js
+++ b/src/embind/embind.js
@@ -493,23 +493,16 @@ function __embind_register_vector(
});
}
-// hang onto your hats, guys, we're going to try to make this one registration work for the class and all its
-// derived classes
-
function __embind_register_class(
classType,
pointerType,
constPointerType,
name,
- getDynamicPointerType,
destructor
) {
name = Pointer_stringify(name);
destructor = FUNCTION_TABLE[destructor];
- if (getDynamicPointerType) {
- getDynamicPointerType = FUNCTION_TABLE[getDynamicPointerType];
- }
-
+
var Handle = createNamedFunction(name, function(ptr) {
var h = function() {
if(h.operator_call !== undefined) {
@@ -521,7 +514,7 @@ function __embind_register_class(
h.count = {value: 1};
h.ptr = ptr;
-
+
for(var prop in Handle.prototype) {
var dp = Object.getOwnPropertyDescriptor(Handle.prototype, prop);
Object.defineProperty(h, prop, dp);
@@ -566,6 +559,8 @@ function __embind_register_class(
return body.apply(this, arguments);
});
constructor.prototype = Handle.prototype;
+ constructor.classType = classType;
+
registerType(classType, name, {
name: name,
@@ -584,14 +579,14 @@ function __embind_register_class(
registerType(pointerType, pointerName, {
name: pointerName,
fromWireType: function(ptr) {
- var dynamicType = getDynamicPointerType && getDynamicPointerType(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) {
- return new Handle(ptr); // I suppose we could work our way up the inheritance tree...
+ return new Handle(ptr);
}
dynamicType = requireRegisteredType(dynamicType.pointerType);
return dynamicType.fromWireTypeStatic(ptr);
@@ -607,19 +602,6 @@ function __embind_register_class(
var constPointerName = name + ' const*';
registerType(constPointerType, constPointerName, {
name: constPointerName,
- fromWireType: function(ptr) {
- var dynamicType = getDynamicPointerType && getDynamicPointerType(ptr);
- if (dynamicType === null || dynamicType === pointerType) {
- return new Handle(ptr);
- }
- try {
- dynamicType = requireRegisteredType(dynamicType);
- } catch (err) {
- return new Handle(ptr); // I suppose we could work our way up the inheritance tree...
- }
- dynamicType = requireRegisteredType(dynamicType.pointerType);
- return dynamicType.fromWireType(ptr);
- },
toWireType: function(destructors, o) {
return o.ptr;
}
@@ -628,112 +610,6 @@ function __embind_register_class(
exposePublicSymbol(name, constructor);
}
-//function __embind_register_class(
-// classType,
-// pointerType,
-// constPointerType,
-// name,
-// destructor
-//) {
-// name = Pointer_stringify(name);
-// destructor = FUNCTION_TABLE[destructor];
-//
-// var Handle = createNamedFunction(name, function(ptr) {
-// var h = function() {
-// if(h.operator_call !== undefined) {
-// return h.operator_call.apply(h, arguments);
-// } else {
-// throw new BindingError(name + ' does not define call operator');
-// }
-// };
-//
-// h.count = {value: 1};
-// h.ptr = ptr;
-//
-// for(var prop in Handle.prototype) {
-// var dp = Object.getOwnPropertyDescriptor(Handle.prototype, prop);
-// Object.defineProperty(h, prop, dp);
-// }
-//
-// return h;
-// });
-//
-// 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) {
-// destructor(this.ptr);
-// }
-// this.ptr = undefined;
-// };
-//
-// var constructor = createNamedFunction(name, function() {
-// var body = constructor.body;
-// return body.apply(this, arguments);
-// });
-// constructor.prototype = Handle.prototype;
-//
-// registerType(classType, name, {
-// name: name,
-// constructor: constructor,
-// Handle: Handle,
-// fromWireType: function(ptr) {
-// return new Handle(ptr);
-// },
-// toWireType: function(destructors, o) {
-// return o.ptr;
-// }
-// });
-//
-// var pointerName = name + '*';
-// registerType(pointerType, pointerName, {
-// name: pointerName,
-// fromWireType: function(ptr) {
-// // based on the fully downcast type of the pointer,
-//
-// return new Handle(ptr); // if me
-// },
-// toWireType: function(destructors, o) {
-// return o.ptr;
-// }
-// });
-//
-// var constPointerName = name + ' const*';
-// registerType(constPointerType, constPointerName, {
-// name: constPointerName,
-// fromWireType: function(ptr) {
-// return new Handle(ptr);
-// },
-// toWireType: function(destructors, o) {
-// return o.ptr;
-// }
-// });
-//
-// exposePublicSymbol(name, constructor);
-//}
-//
function __embind_register_class_constructor(
classType,
argCount,
diff --git a/system/include/emscripten/bind.h b/system/include/emscripten/bind.h
index 96e8dda5..54c017ef 100755
--- a/system/include/emscripten/bind.h
+++ b/system/include/emscripten/bind.h
@@ -104,7 +104,6 @@ namespace emscripten {
TYPEID pointerType,
TYPEID constPointerType,
const char* className,
- GenericFunction getDynamicTypeInfo,
GenericFunction destructor);
void _embind_register_class_constructor(
@@ -267,16 +266,16 @@ namespace emscripten {
// FUNCTIONS
////////////////////////////////////////////////////////////////////////////////
+ extern "C" {
+ int __getDynamicPointerType(int p);
+ int __dynamicPointerCast(int p, int from, int to);
+ }
+
template<typename FromType, typename ToType>
ToType& performCast(FromType& from) {
return *dynamic_cast<ToType*>(&from);
};
- template<typename PointerType>
- internal::TYPEID getDynamicPointerType(PointerType *p) {
- return reinterpret_cast<internal::TYPEID>(&typeid(*p));
- };
-
template<typename FromRawType, typename ToRawType>
std::shared_ptr<ToRawType> performPointerCast(std::shared_ptr<FromRawType> from) {
return std::shared_ptr<ToRawType>(from, dynamic_cast<ToRawType*>(from.get()));
@@ -662,7 +661,6 @@ namespace emscripten {
TypeID<AllowedRawPointer<ClassType>>::get(),
TypeID<AllowedRawPointer<const ClassType>>::get(),
name,
- reinterpret_cast<GenericFunction>(&getDynamicPointerType<ClassType>),
reinterpret_cast<GenericFunction>(&raw_destructor<ClassType>));
}
diff --git a/system/lib/embind/bind.cpp b/system/lib/embind/bind.cpp
index befce08b..c7c1f4b4 100755
--- a/system/lib/embind/bind.cpp
+++ b/system/lib/embind/bind.cpp
@@ -1,7 +1,43 @@
#include <emscripten/bind.h>
+#include <..\lib\libcxxabi\src\private_typeinfo.h>
+#include <list>
+#include <vector>
+#include <emscripten/emscripten.h>
using namespace emscripten;
+namespace __cxxabiv1 {
+ std::vector<const __class_type_info*> __getBaseClasses(const __class_type_info* cti) {
+ std::vector<const __class_type_info*> bases;
+
+ const __si_class_type_info* scti = dynamic_cast<const __si_class_type_info*>(cti);
+ if (scti) {
+ bases.emplace_back(scti->__base_type);
+ } else {
+ const __vmi_class_type_info* vcti = dynamic_cast<const __vmi_class_type_info*>(cti);
+ if (vcti) {
+ for (int i = 0; i < vcti->__base_count; i++) {
+ bases.emplace_back(vcti->__base_info[i].__base_type);
+ }
+ }
+ }
+ 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) {
+ std::vector<const __class_type_info*> newPath(path);
+ newPath.emplace_back(dv);
+ if (dv == bs) {
+ paths.emplace_back(newPath);
+ } else {
+ std::vector<const __class_type_info*> bases = __getBaseClasses(dv);
+ for (int i = 0; i < bases.size(); i++) {
+ __getDerivationPaths1(bases[i], bs, newPath, paths);
+ }
+ }
+ }
+}
+
namespace emscripten {
namespace internal {
void registerStandardTypes() {
@@ -30,5 +66,71 @@ namespace emscripten {
_embind_register_emval(TypeID<val>::get(), "emscripten::val");
}
}
+
+ extern "C" {
+ // These three routines constitute an extension to the compiler's support for dynamic type conversion.
+ // 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) {
+ std::vector<std::vector<const __cxxabiv1::__class_type_info*>> paths;
+
+ const std::type_info* dv1 = (std::type_info*)dv;
+ const std::type_info* bs1 = (std::type_info*)bs;
+ const __cxxabiv1::__class_type_info* dv2 = dynamic_cast<const __cxxabiv1::__class_type_info*>(dv1);
+ 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);
+ }
+
+ 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]);
+ }
+ pathsAsTypeInfo.emplace_back(pathAsTypeInfo);
+ }
+
+ return pathsAsTypeInfo;
+ }
+
+ // We bind __getDerivationPaths 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.
+ EMSCRIPTEN_BINDINGS(([]() {
+ function("__getDerivationPaths", &__getDerivationPaths);
+ }));
+
+ // __getDynamicPointerType returns (for polymorphic types only!) the type of the instance actually
+ // pointed to.
+ 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 must 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 from, int to) {
+ // The final parameter is a place-holder for a hint, a feature which is not currently implemented
+ // in the emscripten runtime. The compiler passes a dummy value of -1, and so do we.
+ return (int)__dynamic_cast((void *)p, (const std::type_info*)from, (const std::type_info *)to, -1);
+ }
+ }
}
}
+
+
+