diff options
| author | Marc Gilleron <marc.gilleron@gmail.com> | 2022-09-20 00:29:39 +0100 |
|---|---|---|
| committer | Marc Gilleron <marc.gilleron@gmail.com> | 2022-09-21 19:31:30 +0100 |
| commit | 5de2c059d1e793f37ed4e128694c29a15eed313d (patch) | |
| tree | de1928f3d49c9f34c20d72c5de1fae453e9e6556 /src/core/class_db.cpp | |
| parent | a330342e4fd9f19edd2733afdc0f7c75179bf9c8 (diff) | |
| download | redot-cpp-5de2c059d1e793f37ed4e128694c29a15eed313d.tar.gz | |
Fix deriving a custom class with virtual methods
Diffstat (limited to 'src/core/class_db.cpp')
| -rw-r--r-- | src/core/class_db.cpp | 19 |
1 files changed, 14 insertions, 5 deletions
diff --git a/src/core/class_db.cpp b/src/core/class_db.cpp index 9393815..4ed73f3 100644 --- a/src/core/class_db.cpp +++ b/src/core/class_db.cpp @@ -277,20 +277,29 @@ void ClassDB::bind_integer_constant(const char *p_class_name, const char *p_enum } GDNativeExtensionClassCallVirtual ClassDB::get_virtual_func(void *p_userdata, const char *p_name) { + // This is called by Godot the first time it calls a virtual function, and it caches the result, per object instance. + // Because of this, it can happen from different threads at once. + // It should be ok not using any mutex as long as we only READ data. + const char *class_name = (const char *)p_userdata; std::unordered_map<std::string, ClassInfo>::iterator type_it = classes.find(class_name); ERR_FAIL_COND_V_MSG(type_it == classes.end(), nullptr, "Class doesn't exist."); - ClassInfo &type = type_it->second; + const ClassInfo *type = &type_it->second; + + // Find method in current class, or any of its parent classes (Godot classes not included) + while (type != nullptr) { + std::unordered_map<std::string, GDNativeExtensionClassCallVirtual>::const_iterator method_it = type->virtual_methods.find(p_name); - std::unordered_map<std::string, GDNativeExtensionClassCallVirtual>::iterator method_it = type.virtual_methods.find(p_name); + if (method_it != type->virtual_methods.end()) { + return method_it->second; + } - if (method_it == type.virtual_methods.end()) { - return nullptr; + type = type->parent_ptr; } - return method_it->second; + return nullptr; } void ClassDB::bind_virtual_method(const char *p_class, const char *p_method, GDNativeExtensionClassCallVirtual p_call) { |
