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

GDExtension: Provide free_property_list_func with length of array #91179

Merged

Conversation

Bromeon
Copy link
Contributor

@Bromeon Bromeon commented Apr 25, 2024

Closes godotengine/godot-proposals#9462.

That issue contains a detailed rationale, but the TLDR is that the length information helps the binding side to know the length of the allocation. It is the equivalent of #89055 but for extension class methods, not script instance methods.

Would be nice to include in 4.3, as we'd have to introduce yet another struct version just for this otherwise 🙂

core/object/class_db.cpp Outdated Show resolved Hide resolved
core/object/object.cpp Show resolved Hide resolved
Copy link
Contributor

@dsnopek dsnopek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

Overall, the code looks great to me! (Although the nit that Raul points out should be fixed.)

I tested this with godot-cpp master (plus PR godotengine/godot-cpp#1450) and with the Godot 4.2 version of godot-cpp, in order to test that the legacy support is working. Everything seemed to work fine!

I agree that it would be nice to get this in Godot 4.3, both so we don't have to make a new struct and because it matches the script instance changes also made for Godot 4.3. I think this change is simple and small enough that it should be safe to do.

@@ -256,6 +256,7 @@ typedef struct {

typedef const GDExtensionPropertyInfo *(*GDExtensionClassGetPropertyList)(GDExtensionClassInstancePtr p_instance, uint32_t *r_count);
typedef void (*GDExtensionClassFreePropertyList)(GDExtensionClassInstancePtr p_instance, const GDExtensionPropertyInfo *p_list);
typedef void (*GDExtensionClassFreePropertyList2)(GDExtensionClassInstancePtr p_instance, const GDExtensionPropertyInfo *p_list, uint32_t p_count);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Raul pointed this out on the godot-cpp PR - the const here is actually incorrect (because we're freeing the memory this points at), and we're working around it in godot-cpp with a const_cast. This would also be a good time to fix that as well!

Suggested change
typedef void (*GDExtensionClassFreePropertyList2)(GDExtensionClassInstancePtr p_instance, const GDExtensionPropertyInfo *p_list, uint32_t p_count);
typedef void (*GDExtensionClassFreePropertyList2)(GDExtensionClassInstancePtr p_instance, GDExtensionPropertyInfo *p_list, uint32_t p_count);

Copy link
Contributor

@dsnopek dsnopek Apr 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or, hrm... Thinking about this a little bit more, I'm not sure const is incorrect. If we remove the const, then Godot will have to do the const_cast in order to call this function!

get_property_list returns const GDExtensionPropertyInfo * because we don't want Godot to modify this data, it's "owned" by the GDExtension. But since it will have a const GDExtensionPropertyInfo *, Godot can't call free_property_list with a GDExtensionPropertyInfo * without casting it. But, arguably, it'd be better for the GDExtension to do the cast because it's the one that "owns" this data, not Godot.

So, on second thought, maybe const is correct, and we need to update the comment in godot-cpp about it being incorrect?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isn't it then get_property_list that's wrong? i think it returns a const pointer, but that pointer is later gonna be freed so it shouldn't be a const pointer?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's getting returned to Godot, though, and it's not Godot that's going to free it. It's going to pass it back to the GDExtension to do the freeing. From the perspective of Godot, I feel like a const pointer is correct.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

from the perspective of godot, isn't this effectively the same as a normal alloc + free (except that you're given initialized memory here)? like sure the gdextension is who actually performs the logic to do the freeing, but the same is true for calling the free function for a memory allocator. the memory allocator is actually the one freeing the memory but we're still responsible for triggering that logic by calling free.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To my understanding, "able to free" doesn't imply "must not be const".
This works fine in C++:

const int* p = new int(30);
delete p;

Now, C free() does take a non-const pointer, but that's likely due to its age.
There's also some discussion on StackOverflow.

@Bromeon Bromeon force-pushed the feature/free-property-list-count branch from 24ee920 to 27a637d Compare April 27, 2024 12:13
@akien-mga akien-mga merged commit 7dd31b4 into godotengine:master Apr 29, 2024
16 checks passed
@akien-mga
Copy link
Member

Thanks!

@Bromeon Bromeon deleted the feature/free-property-list-count branch April 29, 2024 08:20
@akien-mga akien-mga changed the title GDExtension: provide free_property_list_func with length of array GDExtension: Provide free_property_list_func with length of array May 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Not Critical
Development

Successfully merging this pull request may close these issues.

Godot should pass count when freeing the property list of GDExtension classes
5 participants