#include #include <..\lib\libcxxabi\src\private_typeinfo.h> #include #include #include using namespace emscripten; namespace __cxxabiv1 { std::vector __getBaseClasses(const __class_type_info* cti) { std::vector bases; const __si_class_type_info* scti = dynamic_cast(cti); if (scti) { bases.emplace_back(scti->__base_type); } else { const __vmi_class_type_info* vcti = dynamic_cast(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::vectorpath, std::vector>& paths) { std::vector newPath(path); newPath.emplace_back(dv); if (dv == bs) { paths.emplace_back(newPath); } else { std::vector bases = __getBaseClasses(dv); for (int i = 0; i < bases.size(); i++) { __getDerivationPaths1(bases[i], bs, newPath, paths); } } } } namespace emscripten { namespace internal { void registerStandardTypes() { static bool first = true; if (first) { first = false; _embind_register_void(TypeID::get(), "void"); _embind_register_bool(TypeID::get(), "bool", true, false); _embind_register_integer(TypeID::get(), "char"); _embind_register_integer(TypeID::get(), "signed char"); _embind_register_integer(TypeID::get(), "unsigned char"); _embind_register_integer(TypeID::get(), "short"); _embind_register_integer(TypeID::get(), "unsigned short"); _embind_register_integer(TypeID::get(), "int"); _embind_register_integer(TypeID::get(), "unsigned int"); _embind_register_integer(TypeID::get(), "long"); _embind_register_integer(TypeID::get(), "unsigned long"); _embind_register_float(TypeID::get(), "float"); _embind_register_float(TypeID::get(), "double"); _embind_register_cstring(TypeID::get(), "std::string"); _embind_register_emval(TypeID::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> __getDerivationPaths(int dv, const int bs) { std::vector> 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(dv1); const __cxxabiv1::__class_type_info* bs2 = dynamic_cast(bs1); if (dv2 && bs2) { __cxxabiv1::__getDerivationPaths1(dv2, bs2, std::vector(), paths); } std::vector> pathsAsTypeInfo; for (int i = 0; i < paths.size(); i++) { std::vector 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(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); } } } }