summaryrefslogtreecommitdiffstats
path: root/src/core/class_db.cpp
diff options
context:
space:
mode:
authorMarc Gilleron <marc.gilleron@gmail.com>2022-09-20 00:29:39 +0100
committerMarc Gilleron <marc.gilleron@gmail.com>2022-09-21 19:31:30 +0100
commit5de2c059d1e793f37ed4e128694c29a15eed313d (patch)
treede1928f3d49c9f34c20d72c5de1fae453e9e6556 /src/core/class_db.cpp
parenta330342e4fd9f19edd2733afdc0f7c75179bf9c8 (diff)
downloadredot-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.cpp19
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) {