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

Set vararg methods' ptrcall of builtin classes, and let them can be called without arguments. #76047

Conversation

Daylily-Zeleen
Copy link
Contributor

@Daylily-Zeleen Daylily-Zeleen commented Apr 14, 2023

  1. Set VariantBuiltInMethodInfo::ptrcall for builtin vararg methods.
  2. Let builtin vararg methods' ptrcall can be called without arguments.

I don't not the reason why the origin logic set vararg methods' VariantBuiltInMethodInfo::ptrcall to nullptr, I just set them like normal method, and in my test, it work fine.

This pr is made for implementing builtin classes' vararg methods in gdextension( refer to this pr #1091).

@Daylily-Zeleen Daylily-Zeleen force-pushed the daylily-zeleen/builtin_vararg_ptrcall branch from 0333954 to 10546d9 Compare April 14, 2023 08:15
@Daylily-Zeleen Daylily-Zeleen marked this pull request as ready for review April 14, 2023 08:34
@Daylily-Zeleen Daylily-Zeleen requested a review from a team as a code owner April 14, 2023 08:34
@Daylily-Zeleen Daylily-Zeleen changed the title Set builtin varrarg ptrcalls, called without arg. Set varrarg methods of builtin classes' ptrcalls, and let them can be called without arguments. Apr 14, 2023
@Daylily-Zeleen Daylily-Zeleen changed the title Set varrarg methods of builtin classes' ptrcalls, and let them can be called without arguments. Set varrarg methods' ptrcall of builtin classes, and let them can be called without arguments. Apr 14, 2023
@YuriSizov YuriSizov added this to the 4.x milestone Apr 14, 2023
@dsnopek
Copy link
Contributor

dsnopek commented Jun 9, 2023

Thanks!

This works in my testing along with the godot-cpp PR godotengine/godot-cpp#1091

The one thing I'm unsure about is using the lambda function to make the argument pointer.

Why not convert this code:

LocalVector<Variant> vars;
vars.resize(p_argcount);
LocalVector<const Variant *> vars_ptrs;
vars_ptrs.resize(p_argcount);
for (int i = 0; i < p_argcount; i++) {
	vars[i] = PtrToArg<Variant>::convert(p_args[i]);
	vars_ptrs[i] = &vars[i];
}                                

... into something like:

LocalVector<Variant> vars;
LocalVector<const Variant *> vars_ptrs;
if (p_argcount > 0) {
	vars.resize(p_argcount);
	vars_ptrs.resize(p_argcount);
	for (int i = 0; i < p_argcount; i++) {
		vars[i] = PtrToArg<Variant>::convert(p_args[i]);
		vars_ptrs[i] = &vars[i];
	}
} else {
	vars.push_back(Variant());
	vars_ptrs.push_back(&vars[0]);
}

That seems much simpler and easier to understand to me, and it avoids a lambda, which we don't use much in Godot.

@Daylily-Zeleen Daylily-Zeleen force-pushed the daylily-zeleen/builtin_vararg_ptrcall branch 2 times, most recently from dbbab3d to 8e566ee Compare June 25, 2023 12:01
@Daylily-Zeleen
Copy link
Contributor Author

That seems much simpler and easier to understand to me, and it avoids a lambda, which we don't use much in Godot.

Because zero argument calling sill need to memnew a Variant, which we know that this value has no real meaning.
To avoid memnew a unsued Variant for zero argument calling every time, I use a lambda to return a static const const Variant **, which means that it only mennew once if it is needed.

Of course, this only a micro optimization.
Accroding to your comment, I think the readability of code is more important, so I modified this pr to avoid using lamda function.

@dsnopek dsnopek requested a review from a team July 14, 2023 21:49
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!

With the latest changes, this looks great to me! And it's working perfectly from the perspective of GDExtension (via PR godotengine/godot-cpp#1091).

However, it'd be great to get a review from someone on the @godotengine/core team, to double check that this wouldn't have any unexpected implications elsewhere.

@rburing
Copy link
Member

rburing commented Sep 1, 2023

The two ptrcall methods changed here are in the two macros VARARG_CLASS and VARARG_CLASS1, which are used in the two macros bind_custom and bind_custom1, which in turn are used in 6 places, so m_method_ptr can be one of

  • _VariantCall::func_Callable_call
  • _VariantCall::func_Callable_call_deferred
  • _VariantCall::func_Callable_rpc
  • _VariantCall::func_Callable_bind
  • _VariantCall::func_Signal_emit
  • _VariantCall::func_Callable_rpc_id

From a glance these all seem to support the case p_argcount == 0 and p_arguments == nullptr just fine, so the changes to the two ptrcall methods could just be reduced to:

    m_method_ptr(&base, vars_ptrs.ptr(), p_argcount, ret, ce);

avoiding the pointless Variant allocation.

If I'm wrong and one of the methods actually doesn't handle the case gracefully, then I propose handling it there (should be easy).

@Daylily-Zeleen Daylily-Zeleen force-pushed the daylily-zeleen/builtin_vararg_ptrcall branch from 8e566ee to 67e1401 Compare September 1, 2023 16:35
@Daylily-Zeleen
Copy link
Contributor Author

Daylily-Zeleen commented Sep 1, 2023

@rburing Now I remove the branch of p_argcount<=0, and do some simple test about calling call, bind, call_deferred of Callable and Signal::emit without argument, the result is work fine.
I roughly traced the mechanism of Callable::rpc and Callable::rpc_id, it seems that calling callp, too. I think these two methods should work fine, too.

I'm not sure this change is safe or not, please review carefully.

Copy link
Member

@rburing rburing left a comment

Choose a reason for hiding this comment

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

Looks good to me.

Comment on lines -564 to +565
vars.resize(p_argcount); \
LocalVector<const Variant *> vars_ptrs; \
vars.resize(p_argcount); \
Copy link
Member

Choose a reason for hiding this comment

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

This reordering (leftover from the previous version) is not necessary, but it doesn't hurt either.

@akien-mga akien-mga changed the title Set varrarg methods' ptrcall of builtin classes, and let them can be called without arguments. Set vararg methods' ptrcall of builtin classes, and let them can be called without arguments. Sep 1, 2023
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 for your continued work on this!

I just retested the latest PR with godot-cpp, and it seems to be working just fine, including when passing no arguments to a vararg function.

@akien-mga akien-mga merged commit ec517dc into godotengine:master Sep 2, 2023
15 checks passed
@akien-mga
Copy link
Member

Thanks!

@Daylily-Zeleen Daylily-Zeleen deleted the daylily-zeleen/builtin_vararg_ptrcall branch September 3, 2023 01:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants