Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revert the changes from PR #1044 and #1045 and standardize on Object ** encoding in ptrcall #1123

Merged
merged 1 commit into from
Jun 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion binding_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -1887,7 +1887,7 @@ def get_encoded_arg(arg_name, type_name, type_meta):
elif is_engine_class(type_name):
# `{name}` is a C++ wrapper, it contains a field which is the object's pointer Godot expects.
# We have to check `nullptr` because when the caller sends `nullptr`, the wrapper itself will be null.
name = f"({name} != nullptr ? {name}->_owner : nullptr)"
name = f"({name} != nullptr ? &{name}->_owner : nullptr)"
else:
name = f"&{name}"

Expand Down
7 changes: 4 additions & 3 deletions include/godot_cpp/classes/ref.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -229,9 +229,9 @@ class Ref {
template <class T>
struct PtrToArg<Ref<T>> {
_FORCE_INLINE_ static Ref<T> convert(const void *p_ptr) {
// Important: p_ptr is T*, not Ref<T>*, since Object* is what engine gives to ptrcall.
GDExtensionRefPtr ref = (GDExtensionRefPtr)p_ptr;
ERR_FAIL_NULL_V(p_ptr, Ref<T>());
return Ref<T>(reinterpret_cast<T *>(godot::internal::get_object_instance_binding(reinterpret_cast<GDExtensionObjectPtr>(const_cast<void *>(p_ptr)))));
return Ref<T>(reinterpret_cast<T *>(godot::internal::get_object_instance_binding(godot::internal::gdextension_interface_ref_get_object(ref))));
}

typedef Ref<T> EncodeT;
Expand All @@ -253,8 +253,9 @@ struct PtrToArg<const Ref<T> &> {
typedef Ref<T> EncodeT;

_FORCE_INLINE_ static Ref<T> convert(const void *p_ptr) {
GDExtensionRefPtr ref = const_cast<GDExtensionRefPtr>(p_ptr);
ERR_FAIL_NULL_V(p_ptr, Ref<T>());
return Ref<T>(reinterpret_cast<T *>(godot::internal::get_object_instance_binding(reinterpret_cast<GDExtensionObjectPtr>(const_cast<void *>(p_ptr)))));
return Ref<T>(reinterpret_cast<T *>(godot::internal::get_object_instance_binding(godot::internal::gdextension_interface_ref_get_object(ref))));
}
};

Expand Down
4 changes: 2 additions & 2 deletions include/godot_cpp/core/method_ptrcall.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ MAKE_PTRARG_BY_REFERENCE(Variant);
template <class T>
struct PtrToArg<T *> {
_FORCE_INLINE_ static T *convert(const void *p_ptr) {
return reinterpret_cast<T *>(godot::internal::get_object_instance_binding(reinterpret_cast<GDExtensionObjectPtr>(const_cast<void *>(p_ptr))));
return reinterpret_cast<T *>(godot::internal::get_object_instance_binding(*reinterpret_cast<GDExtensionObjectPtr *>(const_cast<void *>(p_ptr))));
}
typedef Object *EncodeT;
_FORCE_INLINE_ static void encode(T *p_var, void *p_ptr) {
Expand All @@ -180,7 +180,7 @@ struct PtrToArg<T *> {
template <class T>
struct PtrToArg<const T *> {
_FORCE_INLINE_ static const T *convert(const void *p_ptr) {
return reinterpret_cast<const T *>(godot::internal::get_object_instance_binding(reinterpret_cast<GDExtensionObjectPtr>(const_cast<void *>(p_ptr))));
return reinterpret_cast<const T *>(godot::internal::get_object_instance_binding(*reinterpret_cast<GDExtensionObjectPtr *>(const_cast<void *>(p_ptr))));
}
typedef const Object *EncodeT;
_FORCE_INLINE_ static void encode(T *p_var, void *p_ptr) {
Expand Down
93 changes: 51 additions & 42 deletions test/project/main.gd
Original file line number Diff line number Diff line change
Expand Up @@ -4,97 +4,106 @@ var custom_signal_emitted = null


func _ready():
var example: Example = $Example

# Signal.
$Example.emit_custom_signal("Button", 42)
example.emit_custom_signal("Button", 42)
assert_equal(custom_signal_emitted, ["Button", 42])

# To string.
assert_equal($Example.to_string(),'Example:[ GDExtension::Example <--> Instance ID:%s ]' % $Example.get_instance_id())
assert_equal(example.to_string(),'Example:[ GDExtension::Example <--> Instance ID:%s ]' % example.get_instance_id())
# It appears there's a bug with instance ids :-(
#assert_equal($Example/ExampleMin.to_string(), 'ExampleMin:[Wrapped:%s]' % $Example/ExampleMin.get_instance_id())

# Call static methods.
assert_equal($Example.test_static(9, 100), 109);
assert_equal(Example.test_static(9, 100), 109);
# It's void and static, so all we know is that it didn't crash.
$Example.test_static2()
Example.test_static2()

# Property list.
$Example.property_from_list = Vector3(100, 200, 300)
assert_equal($Example.property_from_list, Vector3(100, 200, 300))
example.property_from_list = Vector3(100, 200, 300)
assert_equal(example.property_from_list, Vector3(100, 200, 300))

# Call simple methods.
$Example.simple_func()
example.simple_func()
assert_equal(custom_signal_emitted, ['simple_func', 3])
($Example as Example).simple_const_func() # Force use of ptrcall
example.simple_const_func()
assert_equal(custom_signal_emitted, ['simple_const_func', 4])

# Pass custom reference.
assert_equal($Example.custom_ref_func(null), -1)
assert_equal(example.custom_ref_func(null), -1)
var ref1 = ExampleRef.new()
ref1.id = 27
assert_equal($Example.custom_ref_func(ref1), 27)
assert_equal(example.custom_ref_func(ref1), 27)
ref1.id += 1;
assert_equal($Example.custom_const_ref_func(ref1), 28)
assert_equal(example.custom_const_ref_func(ref1), 28)

# Pass core reference.
assert_equal($Example.image_ref_func(null), "invalid")
assert_equal($Example.image_const_ref_func(null), "invalid")
assert_equal(example.image_ref_func(null), "invalid")
assert_equal(example.image_const_ref_func(null), "invalid")
var image = Image.new()
assert_equal($Example.image_ref_func(image), "valid")
assert_equal($Example.image_const_ref_func(image), "valid")
assert_equal(example.image_ref_func(image), "valid")
assert_equal(example.image_const_ref_func(image), "valid")

# Return values.
assert_equal($Example.return_something("some string"), "some string42")
assert_equal($Example.return_something_const(), get_viewport())
var null_ref = $Example.return_empty_ref()
assert_equal(example.return_something("some string"), "some string42")
assert_equal(example.return_something_const(), get_viewport())
var null_ref = example.return_empty_ref()
assert_equal(null_ref, null)
var ret_ref = $Example.return_extended_ref()
var ret_ref = example.return_extended_ref()
assert_not_equal(ret_ref.get_instance_id(), 0)
assert_equal(ret_ref.get_id(), 0)
assert_equal($Example.get_v4(), Vector4(1.2, 3.4, 5.6, 7.8))
assert_equal($Example.test_node_argument($Example), $Example)
assert_equal(example.get_v4(), Vector4(1.2, 3.4, 5.6, 7.8))
assert_equal(example.test_node_argument(example), example)

# VarArg method calls.
var var_ref = ExampleRef.new()
assert_not_equal($Example.extended_ref_checks(var_ref).get_instance_id(), var_ref.get_instance_id())
assert_equal($Example.varargs_func("some", "arguments", "to", "test"), 4)
assert_equal($Example.varargs_func_nv("some", "arguments", "to", "test"), 46)
$Example.varargs_func_void("some", "arguments", "to", "test")
assert_not_equal(example.extended_ref_checks(var_ref).get_instance_id(), var_ref.get_instance_id())
assert_equal(example.varargs_func("some", "arguments", "to", "test"), 4)
assert_equal(example.varargs_func_nv("some", "arguments", "to", "test"), 46)
example.varargs_func_void("some", "arguments", "to", "test")
assert_equal(custom_signal_emitted, ["varargs_func_void", 5])

# Method calls with default values.
assert_equal($Example.def_args(), 300)
assert_equal($Example.def_args(50), 250)
assert_equal($Example.def_args(50, 100), 150)
assert_equal(example.def_args(), 300)
assert_equal(example.def_args(50), 250)
assert_equal(example.def_args(50, 100), 150)

# Array and Dictionary
assert_equal($Example.test_array(), [1, 2])
assert_equal($Example.test_tarray(), [ Vector2(1, 2), Vector2(2, 3) ])
assert_equal($Example.test_dictionary(), {"hello": "world", "foo": "bar"})
assert_equal(example.test_array(), [1, 2])
assert_equal(example.test_tarray(), [ Vector2(1, 2), Vector2(2, 3) ])
assert_equal(example.test_dictionary(), {"hello": "world", "foo": "bar"})
var array: Array[int] = [1, 2, 3]
assert_equal($Example.test_tarray_arg(array), 6)
assert_equal(example.test_tarray_arg(array), 6)

# String += operator
assert_equal($Example.test_string_ops(), "ABCĎE")
assert_equal(example.test_string_ops(), "ABCĎE")

# PackedArray iterators
assert_equal($Example.test_vector_ops(), 105)
assert_equal(example.test_vector_ops(), 105)

# Properties.
assert_equal($Example.group_subgroup_custom_position, Vector2(0, 0))
$Example.group_subgroup_custom_position = Vector2(50, 50)
assert_equal($Example.group_subgroup_custom_position, Vector2(50, 50))
assert_equal(example.group_subgroup_custom_position, Vector2(0, 0))
example.group_subgroup_custom_position = Vector2(50, 50)
assert_equal(example.group_subgroup_custom_position, Vector2(50, 50))

# Constants.
assert_equal($Example.FIRST, 0)
assert_equal($Example.ANSWER_TO_EVERYTHING, 42)
assert_equal($Example.CONSTANT_WITHOUT_ENUM, 314)
assert_equal(Example.FIRST, 0)
assert_equal(Example.ANSWER_TO_EVERYTHING, 42)
assert_equal(Example.CONSTANT_WITHOUT_ENUM, 314)

# BitFields.
assert_equal(Example.FLAG_ONE, 1)
assert_equal(Example.FLAG_TWO, 2)
assert_equal($Example.test_bitfield(0), 0)
assert_equal($Example.test_bitfield(Example.FLAG_ONE | Example.FLAG_TWO), 3)
assert_equal(example.test_bitfield(0), 0)
assert_equal(example.test_bitfield(Example.FLAG_ONE | Example.FLAG_TWO), 3)

# Virtual method.
var event = InputEventKey.new()
event.key_label = KEY_H
event.unicode = 72
get_viewport().push_input(event)
assert_equal(custom_signal_emitted, ["_input: H", 72])

exit_with_status()

Expand Down
4 changes: 2 additions & 2 deletions test/project/main.tscn
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
[gd_scene load_steps=2 format=3 uid="uid://dmx2xuigcpvt4"]

[ext_resource type="Script" path="res://main.gd" id="1_c326s"]
[ext_resource type="Script" path="res://main.gd" id="1_qesh5"]

[node name="Node" type="Node"]
script = ExtResource("1_c326s")
script = ExtResource("1_qesh5")

[node name="Example" type="Example" parent="."]

Expand Down
2 changes: 1 addition & 1 deletion test/project/project.godot
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ config_version=5

config/name="GDExtension Test Project"
run/main_scene="res://main.tscn"
config/features=PackedStringArray("4.0")
config/features=PackedStringArray("4.1")
config/icon="res://icon.png"

[native_extensions]
Expand Down
7 changes: 7 additions & 0 deletions test/src/example.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -348,3 +348,10 @@ bool Example::_has_point(const Vector2 &point) const {

return false;
}

void Example::_input(const Ref<InputEvent> &event) {
const InputEventKey *key_event = Object::cast_to<const InputEventKey>(*event);
if (key_event) {
emit_custom_signal(String("_input: ") + key_event->get_key_label(), key_event->get_unicode());
}
}
2 changes: 2 additions & 0 deletions test/src/example.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <godot_cpp/classes/control.hpp>
#include <godot_cpp/classes/global_constants.hpp>
#include <godot_cpp/classes/image.hpp>
#include <godot_cpp/classes/input_event_key.hpp>
#include <godot_cpp/classes/viewport.hpp>

#include <godot_cpp/core/binder_common.hpp>
Expand Down Expand Up @@ -129,6 +130,7 @@ class Example : public Control {

// Virtual function override (no need to bind manually).
virtual bool _has_point(const Vector2 &point) const override;
virtual void _input(const Ref<InputEvent> &event) override;
};

VARIANT_ENUM_CAST(Example::Constants);
Expand Down