Skip to content

Commit 6b27168

Browse files
committed
Fixing reference return
1 parent adbc0bf commit 6b27168

File tree

4 files changed

+69
-14
lines changed

4 files changed

+69
-14
lines changed

include/godot_cpp/classes/ref.hpp

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,15 @@ class Ref {
112112
}
113113

114114
operator Variant() const {
115-
return Variant(reference);
115+
if (reference != nullptr) {
116+
// When assigning a variant this way it's not increasing the refcount like it should
117+
// not sure if this is a workaround or a proper solution...
118+
reference->reference();
119+
return Variant(reference);
120+
} else {
121+
// no object? return NIL variant
122+
return Variant();
123+
}
116124
}
117125

118126
void operator=(const Ref &p_from) {
@@ -186,6 +194,20 @@ class Ref {
186194
r.reference = nullptr;
187195
}
188196

197+
template <class T_Other>
198+
Ref(const Ref<T_Other> &&p_other) {
199+
RefCounted *refb = const_cast<RefCounted *>(static_cast<const RefCounted *>(p_other.ptr()));
200+
if (!refb) {
201+
unref();
202+
return;
203+
}
204+
205+
Ref r;
206+
r.reference = Object::cast_to<T>(refb);
207+
ref(r);
208+
r.reference = nullptr;
209+
}
210+
189211
Ref(T *p_reference) {
190212
if (p_reference) {
191213
ref_pointer(p_reference);
@@ -246,7 +268,7 @@ struct PtrToArg<Ref<T>> {
246268
typedef Ref<T> EncodeT;
247269

248270
_FORCE_INLINE_ static void encode(Ref<T> p_val, const void *p_ptr) {
249-
*(void **)p_ptr = p_val->_owner;
271+
godot::internal::gdn_interface->reference_assign((GDNativeObjectPtr)p_ptr, (GDNativeObjectPtr)p_val->_owner);
250272
}
251273
};
252274

test/demo/main.gd

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,12 @@ func _ready():
99
($Example as Example).simple_const_func() # Force use of ptrcall
1010
prints("returned", $Example.return_something("some string"))
1111
prints("returned const", $Example.return_something_const())
12-
prints("returned ref", $Example.return_extended_ref())
12+
13+
prints("returned example ref object: ", $Example.return_extended_ref())
14+
1315
var ref = ExampleRef.new()
1416
prints("sending ref: ", ref.get_instance_id(), "returned ref: ", $Example.extended_ref_checks(ref).get_instance_id())
17+
1518
prints("vararg args", $Example.varargs_func("some", "arguments", "to", "test"))
1619

1720
prints("test array", $Example.test_array())

test/src/example.cpp

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,22 +38,26 @@
3838

3939
using namespace godot;
4040

41+
uint64_t ExampleRef::instance_count = 0;
42+
4143
ExampleRef::ExampleRef() {
42-
UtilityFunctions::print("ExampleRef created.");
44+
instance_count++;
45+
UtilityFunctions::print("ExampleRef created. Our total instance count is now: ", instance_count);
4346
}
4447

4548
ExampleRef::~ExampleRef() {
46-
UtilityFunctions::print("ExampleRef destroyed.");
49+
instance_count--;
50+
UtilityFunctions::print("ExampleRef destroyed. Our total instance count is now: ", instance_count);
4751
}
4852

4953
void Example::_bind_methods() {
5054
// Methods.
5155
ClassDB::bind_method(D_METHOD("simple_func"), &Example::simple_func);
5256
ClassDB::bind_method(D_METHOD("simple_const_func"), &Example::simple_const_func);
53-
ClassDB::bind_method(D_METHOD("return_something"), &Example::return_something);
57+
ClassDB::bind_method(D_METHOD("return_something", "base"), &Example::return_something);
5458
ClassDB::bind_method(D_METHOD("return_something_const"), &Example::return_something_const);
5559
ClassDB::bind_method(D_METHOD("return_extended_ref"), &Example::return_extended_ref);
56-
ClassDB::bind_method(D_METHOD("extended_ref_checks"), &Example::extended_ref_checks);
60+
ClassDB::bind_method(D_METHOD("extended_ref_checks", "ref"), &Example::extended_ref_checks);
5761

5862
ClassDB::bind_method(D_METHOD("test_array"), &Example::test_array);
5963
ClassDB::bind_method(D_METHOD("test_dictionary"), &Example::test_dictionary);
@@ -73,6 +77,10 @@ void Example::_bind_methods() {
7377
ClassDB::bind_method(D_METHOD("set_custom_position", "position"), &Example::set_custom_position);
7478
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "group_subgroup_custom_position"), "set_custom_position", "get_custom_position");
7579

80+
// ClassDB::bind_method(D_METHOD("get_ref_obj"), &Example::get_ref_obj);
81+
// ClassDB::bind_method(D_METHOD("set_ref_obj", "ref_obj"), &Example::set_ref_obj);
82+
// ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "ref_obj", PROPERTY_HINT_RESOURCE_TYPE, "ExampleRef"), "set_ref_obj", "get_ref_obj");
83+
7684
// Signals.
7785
ADD_SIGNAL(MethodInfo("custom_signal", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::INT, "value")));
7886
ClassDB::bind_method(D_METHOD("emit_custom_signal", "name", "value"), &Example::emit_custom_signal);
@@ -115,15 +123,19 @@ Viewport *Example::return_something_const() const {
115123
return nullptr;
116124
}
117125

118-
ExampleRef *Example::return_extended_ref() const {
119-
return memnew(ExampleRef());
126+
Ref<ExampleRef> Example::return_extended_ref() const {
127+
// When subclassing RefCounted we should ALWAYS use Ref<..> or Godot will start doing confusing things as it will start using reference counting to manage the object.
128+
// We should never instantiate the object directly such as this:
129+
// return memnew(ExampleRef());
130+
131+
Ref<ExampleRef> ref;
132+
ref.instantiate();
133+
return ref;
120134
}
121135

122136
Ref<ExampleRef> Example::extended_ref_checks(Ref<ExampleRef> p_ref) const {
123137
Ref<ExampleRef> ref;
124138
ref.instantiate();
125-
// TODO the returned value gets dereferenced too early and return a null object otherwise.
126-
ref->reference();
127139
UtilityFunctions::print("Example ref checks called with value: ", p_ref->get_instance_id(), ", returning value: ", ref->get_instance_id());
128140
return ref;
129141
}
@@ -165,6 +177,16 @@ Vector2 Example::get_custom_position() const {
165177
return custom_position;
166178
}
167179

180+
/*
181+
void Example::set_ref_obj(const Ref<ExampleRef> p_ref) {
182+
ref_obj = p_ref;
183+
}
184+
185+
Ref<ExampleRef> Example::get_ref_obj() const {
186+
return ref_obj;
187+
}
188+
*/
189+
168190
// Virtual function override.
169191
bool Example::_has_point(const Vector2 &point) const {
170192
Label *label = get_node<Label>("Label");

test/src/example.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,18 @@
3939

4040
#include <godot_cpp/classes/control.hpp>
4141
#include <godot_cpp/classes/global_constants.hpp>
42+
#include <godot_cpp/classes/resource.hpp>
4243
#include <godot_cpp/classes/viewport.hpp>
4344

4445
#include <godot_cpp/core/binder_common.hpp>
4546

4647
using namespace godot;
4748

48-
class ExampleRef : public RefCounted {
49-
GDCLASS(ExampleRef, RefCounted);
49+
class ExampleRef : public Resource {
50+
GDCLASS(ExampleRef, Resource);
51+
52+
private:
53+
static uint64_t instance_count;
5054

5155
protected:
5256
static void _bind_methods() {}
@@ -64,6 +68,7 @@ class Example : public Control {
6468

6569
private:
6670
Vector2 custom_position;
71+
// Ref<ExampleRef> ref_obj;
6772

6873
public:
6974
// Constants.
@@ -84,7 +89,7 @@ class Example : public Control {
8489
void simple_const_func() const;
8590
String return_something(const String &base);
8691
Viewport *return_something_const() const;
87-
ExampleRef *return_extended_ref() const;
92+
Ref<ExampleRef> return_extended_ref() const;
8893
Ref<ExampleRef> extended_ref_checks(Ref<ExampleRef> p_ref) const;
8994
Variant varargs_func(const Variant **args, GDNativeInt arg_count, GDNativeCallError &error);
9095
void emit_custom_signal(const String &name, int value);
@@ -96,6 +101,9 @@ class Example : public Control {
96101
void set_custom_position(const Vector2 &pos);
97102
Vector2 get_custom_position() const;
98103

104+
// void set_ref_obj(const Ref<ExampleRef> p_ref);
105+
// Ref<ExampleRef> get_ref_obj() const;
106+
99107
// Virtual function override (no need to bind manually).
100108
virtual bool _has_point(const Vector2 &point) const override;
101109
};

0 commit comments

Comments
 (0)