It is now possible to access base class properties and methods from a derived class (multiple inheritance not yet supported).
This commit is contained in:
Родитель
d893eed16b
Коммит
6c56bdda8d
|
@ -36,6 +36,89 @@ function _embind_repr(v) {
|
|||
|
||||
var typeRegistry = {};
|
||||
|
||||
function resolveType(type) {
|
||||
function createInheritedFunctionOrProperty(baseClassName, name, baseClassPrototype) {
|
||||
if (!type.Handle.prototype.hasOwnProperty(name)) {
|
||||
var desc = Object.getOwnPropertyDescriptor(baseClassPrototype, baseClassName);
|
||||
if (desc) { // some names in the list may not be present in this particular base class
|
||||
if ('get' in desc || 'put' in desc) {
|
||||
Object.defineProperty(type.Handle.prototype, name, desc);
|
||||
} else {
|
||||
type.Handle.prototype[name] = createNamedFunction(name, function() {
|
||||
return baseClassPrototype[baseClassName].apply(this, arguments); // todo: need to upcast "this" pointer
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!type.resolved) {
|
||||
var i, j, rawBaseClassType, baseClassType, name;
|
||||
var names = [];
|
||||
var qualifiedNames = {};
|
||||
var rawBaseClassTypes = Module.__getBaseClasses(type.rawType);
|
||||
for (i = 0; i < rawBaseClassTypes.size(); i++) {
|
||||
rawBaseClassType = rawBaseClassTypes.at(i);
|
||||
baseClassType = typeRegistry[rawBaseClassType];
|
||||
if (baseClassType) {
|
||||
resolveType(baseClassType);
|
||||
var proto = baseClassType.Handle.prototype;
|
||||
for (name in proto) {
|
||||
if (proto.hasOwnProperty(name)) {
|
||||
var qualifiedName = baseClassType.name + "_" + name;
|
||||
// todo: figure out how to exclude casting functions
|
||||
if (['clone', 'move', 'delete'].indexOf(name) < 0) {
|
||||
if (type.Handle.prototype.hasOwnProperty(qualifiedName)) {
|
||||
if (names.indexOf(name) < 0) {
|
||||
names.push(name);
|
||||
}
|
||||
if (names.indexOf(qualifiedName) < 0) {
|
||||
qualifiedNames[name] = qualifiedName;
|
||||
}
|
||||
} else {
|
||||
if (names.indexOf(name) >= 0) {
|
||||
if (names.indexOf(qualifiedName) < 0) {
|
||||
qualifiedNames[name] = qualifiedName;
|
||||
}
|
||||
} else {
|
||||
names.push(name);
|
||||
if (type.Handle.prototype.hasOwnProperty(name) && names.indexOf(qualifiedName) < 0) {
|
||||
qualifiedNames[name] = qualifiedName;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 0; i < rawBaseClassTypes.size(); i++) {
|
||||
rawBaseClassType = rawBaseClassTypes.at(i);
|
||||
baseClassType = typeRegistry[rawBaseClassType];
|
||||
if (baseClassType) {
|
||||
proto = baseClassType.Handle.prototype;
|
||||
for (name in qualifiedNames) {
|
||||
if (qualifiedNames.hasOwnProperty(name)) {
|
||||
createInheritedFunctionOrProperty(name, qualifiedNames[name], proto);
|
||||
}
|
||||
}
|
||||
for (j = 0; j < names.length; j++) {
|
||||
name = names[j];
|
||||
if (!(name in qualifiedNames)) {
|
||||
createInheritedFunctionOrProperty(name, name, proto);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
type.resolved = true;
|
||||
}
|
||||
}
|
||||
|
||||
function resolveBindings() {
|
||||
for (var rawType in typeRegistry) {
|
||||
resolveType(typeRegistry[rawType]);
|
||||
}
|
||||
}
|
||||
|
||||
function registerType(rawType, name, registeredInstance) {
|
||||
if (!rawType) {
|
||||
throw new BindingError('type "' + name + '" must have a positive integer typeid pointer');
|
||||
|
@ -731,8 +814,8 @@ function __embind_register_class(
|
|||
var dp = Object.getOwnPropertyDescriptor(Handle.prototype, prop);
|
||||
Object.defineProperty(h, prop, dp);
|
||||
}
|
||||
|
||||
return h;
|
||||
|
||||
return h;
|
||||
});
|
||||
|
||||
Handle.prototype.clone = function() {
|
||||
|
@ -772,6 +855,7 @@ function __embind_register_class(
|
|||
var registeredClass = new RegisteredPointer(Handle, isPolymorphic, false);
|
||||
var type = registerType(rawType, name, registeredClass);
|
||||
registeredClass.pointeeType = type;
|
||||
|
||||
var registeredClass = new RegisteredPointer(Handle, isPolymorphic, false);
|
||||
registerType(rawPointerType, name + '*', registeredClass);
|
||||
registeredClass.pointeeType = type;
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
using namespace emscripten;
|
||||
|
||||
namespace __cxxabiv1 {
|
||||
std::vector<const __class_type_info*> __getBaseClasses(const __class_type_info* cti) {
|
||||
std::vector<const __class_type_info*> __internalGetBaseClasses(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);
|
||||
|
@ -48,7 +48,7 @@ namespace __cxxabiv1 {
|
|||
if (dv == bs) {
|
||||
paths.emplace_back(newPath);
|
||||
} else {
|
||||
std::vector<const __class_type_info*> bases = __getBaseClasses(dv);
|
||||
std::vector<const __class_type_info*> bases = __internalGetBaseClasses(dv);
|
||||
for (int i = 0; i < bases.size(); i++) {
|
||||
__getDerivationPaths(bases[i], bs, newPath, paths);
|
||||
}
|
||||
|
@ -212,6 +212,15 @@ namespace emscripten {
|
|||
return name;
|
||||
}
|
||||
|
||||
std::vector<int> __getBaseClasses(int tp) {
|
||||
std::vector<const __cxxabiv1::__class_type_info*> baseTypes = __internalGetBaseClasses((const __cxxabiv1::__class_type_info*)tp);
|
||||
std::vector<int> bases;
|
||||
for (int j = 0; j < baseTypes.size(); j++) {
|
||||
bases.emplace_back((int)baseTypes[j]);
|
||||
}
|
||||
return bases;
|
||||
}
|
||||
|
||||
int EMSCRIPTEN_KEEPALIVE __peek32(int p) {
|
||||
return *(int *)p;
|
||||
}
|
||||
|
@ -221,6 +230,7 @@ namespace emscripten {
|
|||
// 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("__getDerivationPath", &__getDerivationPath);
|
||||
function("__getBaseClasses", &__getBaseClasses);
|
||||
function("__peek32", &__peek32);
|
||||
}));
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче