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:
Bill Welden 2013-01-16 14:19:19 -08:00 коммит произвёл Jukka Jylänki
Родитель d893eed16b
Коммит 6c56bdda8d
2 изменённых файлов: 98 добавлений и 4 удалений

Просмотреть файл

@ -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);
}));
}