From 38f1ee741d06e5aedd1ddf397089e8cf0bf75f39 Mon Sep 17 00:00:00 2001 From: Karroffel Date: Wed, 21 Jun 2017 00:42:29 +0200 Subject: [PATCH 1/2] some Ref WIP, memory leaks and invalid returns --- binding_generator.py | 61 +++++++++++++++++++++++++++++++----------- include/core/Godot.hpp | 1 + include/core/Ref.hpp | 29 ++++++++++++++++---- 3 files changed, 70 insertions(+), 21 deletions(-) diff --git a/binding_generator.py b/binding_generator.py index cd969e66b1f5..398193e89907 100644 --- a/binding_generator.py +++ b/binding_generator.py @@ -4,8 +4,11 @@ # comment. +classes = [] + def generate_bindings(path): + global classes classes = json.load(open(path)) icalls = set() @@ -31,8 +34,23 @@ def generate_bindings(path): icall_source_file = open("src/__icalls.cpp", "w+") icall_source_file.write(generate_icall_implementation(icalls)) - - + +def is_reference_type(t): + for c in classes: + if c['name'] != t: + continue + if c['is_reference']: + return True + return False + +def make_gdnative_type(t): + if is_class_type(t): + if is_reference_type(t): + return "Ref<" + strip_name(t) + "> " + else: + return strip_name(t) + " *" + else: + return strip_name(t) + " " def generate_class_header(used_classes, c): @@ -59,6 +77,7 @@ def generate_class_header(used_classes, c): source.append("#include ") + source.append("#include ") if c["base_class"] != "": source.append("#include <" + strip_name(c["base_class"]) + ".hpp>") @@ -104,15 +123,14 @@ def generate_class_header(used_classes, c): method_signature = "" method_signature += "static " if c["singleton"] else "" - method_signature += strip_name(method["return_type"]) - method_signature += " *" if is_class_type(method["return_type"]) else " " + method_signature += make_gdnative_type(method["return_type"]) method_signature += escape_cpp(method["name"]) + "(" - - + + has_default_argument = False for i, argument in enumerate(method["arguments"]): - method_signature += "const " + argument["type"] + (" *" if is_class_type(argument["type"]) else " ") + method_signature += "const " + make_gdnative_type(argument["type"]) method_signature += escape_cpp(argument["name"]) @@ -196,6 +214,7 @@ def generate_class_implementation(icalls, used_classes, c): source.append("") source.append("#include ") + source.append("#include ") source.append("#include ") source.append("") @@ -252,12 +271,11 @@ def generate_class_implementation(icalls, used_classes, c): for method in c["methods"]: method_signature = "" - method_signature += strip_name(method["return_type"]) - method_signature += " *" if is_class_type(method["return_type"]) else " " + method_signature += make_gdnative_type(method["return_type"]) method_signature += strip_name(c["name"]) + "::" + escape_cpp(method["name"]) + "(" for i, argument in enumerate(method["arguments"]): - method_signature += "const " + argument["type"] + (" *" if is_class_type(argument["type"]) else " ") + method_signature += "const " + make_gdnative_type(argument["type"]) method_signature += escape_cpp(argument["name"]) if i != len(method["arguments"]) - 1: @@ -286,7 +304,13 @@ def generate_class_implementation(icalls, used_classes, c): return_statement = "" if method["return_type"] != "void": - return_statement += "return " + ("(" + strip_name(method["return_type"]) + " *) " if is_class_type(method["return_type"]) else "") + if is_class_type(method["return_type"]): + if is_reference_type(method["return_type"]): + return_statement += "return Ref<" + strip_name(method["return_type"]) + ">("; + else: + return_statement += "return " + ("(" + strip_name(method["return_type"]) + " *) " if is_class_type(method["return_type"]) else "") + else: + return_statement += "return " def get_icall_type_name(name): if is_class_type(name): @@ -295,7 +319,7 @@ def get_icall_type_name(name): - if method["is_virtual"] or method["has_varargs"]: + if method["has_varargs"]: if len(method["arguments"]) != 0: source.append("\tVariant __given_args[" + str(len(method["arguments"])) + "];") @@ -347,8 +371,13 @@ def get_icall_type_name(name): if method["return_type"] != "void": cast = "" if is_class_type(method["return_type"]): - cast += "(" + strip_name(method["return_type"]) + " *) (Object *) " - source.append("\treturn " + cast + "__result;") + if is_reference_type(method["return_type"]): + cast += "Ref<" + stip_name(method["return_type"]) + ">(__result);" + else: + cast += "(" + strip_name(method["return_type"]) + " *) (Object *) __result;" + else: + cast += "__result;" + source.append("\treturn " + cast) @@ -369,11 +398,11 @@ def get_icall_type_name(name): return_statement += icall_name + "(mb, (godot_object *) " + core_object_name for arg in method["arguments"]: - return_statement += ", " + escape_cpp(arg["name"]) + return_statement += ", " + escape_cpp(arg["name"]) + (".ptr()" if is_reference_type(arg["type"]) else "") return_statement += ")" - source.append("\t" + return_statement + ";") + source.append("\t" + return_statement + (")" if is_reference_type(method["return_type"]) else "") + ";") source.append("}") source.append("") diff --git a/include/core/Godot.hpp b/include/core/Godot.hpp index 5e0829d990f6..49876cd676f9 100644 --- a/include/core/Godot.hpp +++ b/include/core/Godot.hpp @@ -9,6 +9,7 @@ #include #include +#include #include diff --git a/include/core/Ref.hpp b/include/core/Ref.hpp index 192ba585fc70..2cdbb2592703 100644 --- a/include/core/Ref.hpp +++ b/include/core/Ref.hpp @@ -84,10 +84,17 @@ class Ref { { ref(from); } + + template + void operator=(const Ref &from) + { + Ref n((T *) from.ptr()); + ref(n); + } void operator=(const Variant &variant) { - T *r = variant; + T *r = (T *) (Object *) variant; if (!r) { unref(); return; @@ -101,17 +108,26 @@ class Ref { operator Variant() const { - ref(); - return Variant((Object *) this); + if (reference) reference->reference(); + return Variant((Object *) reference); } + template + Ref(const Ref &from) + { + if (from.ptr()) + ref_pointer((T *) from.ptr()); + else + reference = nullptr; + } Ref(const Ref &from) { reference = nullptr; ref(from); } - + + Ref(T *r) { if (r) @@ -120,10 +136,13 @@ class Ref { reference = nullptr; } + template + Ref(T_Other *r) : Ref((T *) r) {} + Ref(const Variant &variant) { reference = nullptr; - T *r = variant; + T *r = (T *) (Object *) variant; if (!r) { unref(); return; From e1f38654677acad1c929546e2724206bb225e7d1 Mon Sep 17 00:00:00 2001 From: Karroffel Date: Wed, 21 Jun 2017 02:14:54 +0200 Subject: [PATCH 2/2] Wohoo, Ref<>s are now working --- binding_generator.py | 4 ++-- include/core/Godot.hpp | 2 +- include/core/Ref.hpp | 15 ++++++++++----- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/binding_generator.py b/binding_generator.py index 398193e89907..22c2789013a9 100644 --- a/binding_generator.py +++ b/binding_generator.py @@ -306,7 +306,7 @@ def generate_class_implementation(icalls, used_classes, c): if method["return_type"] != "void": if is_class_type(method["return_type"]): if is_reference_type(method["return_type"]): - return_statement += "return Ref<" + strip_name(method["return_type"]) + ">("; + return_statement += "return Ref<" + strip_name(method["return_type"]) + ">::__internal_constructor("; else: return_statement += "return " + ("(" + strip_name(method["return_type"]) + " *) " if is_class_type(method["return_type"]) else "") else: @@ -372,7 +372,7 @@ def get_icall_type_name(name): cast = "" if is_class_type(method["return_type"]): if is_reference_type(method["return_type"]): - cast += "Ref<" + stip_name(method["return_type"]) + ">(__result);" + cast += "Ref<" + stip_name(method["return_type"]) + ">::__internal_constructor(__result);" else: cast += "(" + strip_name(method["return_type"]) + " *) (Object *) __result;" else: diff --git a/include/core/Godot.hpp b/include/core/Godot.hpp index 49876cd676f9..8ad8b3705ea3 100644 --- a/include/core/Godot.hpp +++ b/include/core/Godot.hpp @@ -67,7 +67,7 @@ template struct _ArgCast { static T _arg_cast(Variant a) { - return a.operator T(); + return static_cast(a); } }; diff --git a/include/core/Ref.hpp b/include/core/Ref.hpp index 2cdbb2592703..78b1926cbbd5 100644 --- a/include/core/Ref.hpp +++ b/include/core/Ref.hpp @@ -108,7 +108,6 @@ class Ref { operator Variant() const { - if (reference) reference->reference(); return Variant((Object *) reference); } @@ -130,10 +129,8 @@ class Ref { Ref(T *r) { - if (r) - ref_pointer(r); - else - reference = nullptr; + r->reference(); + reference = r; } template @@ -153,6 +150,14 @@ class Ref { ref(re); re.reference = nullptr; } + + template + static Ref __internal_constructor(T_Other *r) + { + Ref ref; + ref.reference = (T *) r; + return ref; + } inline bool is_valid() const { return reference != nullptr; }