Binding functions with passing by reference arguments


#1

The current binding mechanism is not taking “passing by reference” arguments in to account:

Take GetActorEyesViewPoint in AActor for example:

Here’s the original function signature:

void AActor::GetActorEyesViewPoint( FVector& OutLocation, FRotator& OutRotation ) const

In script:

!loc: Vector3!xyz(0,0,0) !rot: RotationAngles!yaw_pitch_roll(0,0,0) actor_eyes_view_point(loc, rot) // loc and rot failed to be updated

It works as expected after modifying the auto generated binding to something like:

static void mthd_actor_eyes_view_point(SkInvokedMethod * scope_p, SkInstance ** result_pp)
    {
      AActor * this_p = scope_p->this_as<SkUEActor>();
      if (this_p)
        {
        this_p->GetActorEyesViewPoint(scope_p->get_arg<SkVector3>(SkArg_1), scope_p->get_arg<SkRotationAngles>(SkArg_2));
      }
    }

#2

Hi Nate - good point, I actually looked into directly calling UE methods from the binding code instead of going through ProcessEvent(). There are a couple issues with that, e.g. private methods not publicly accessible, and Blueprint overridable methods that would not be properly redirected. But possibly some methods can selectively bypass the ProcessEvent() mechanism and call the method directly. I will investigate this further and get back to you.


#3

As a sidenote, to create a zero vector, you should be able to just say Vector3! (call the default constructor). However this is currently broken but on my task list to fix.


#4

I tried to bind all public methods using the direct call methods instead of ProcessEvent(), but failed to build due to some link errors.

Is it possible to use scope_p->set_arg(SkArg_1, SkVector3::new_instance(params.OutLocation)); to push back updated value from C++ to Skookum?


#5

This would not work, as it would modify only the argument binding, but leave the object and the passed in variable binding unchanged. What you intend to do here is assign a new value to the argument’s SkInstance which can be done by scope_p->get_arg<SkVector3>(SkArg_1) = params.OutLocation.


#6

It doesn’t really help you here, though SkookumScript also has the ability to specify return arguments for arguments that you want to return values. These are specified in a routines parameter list following a semicolon ; - see return-args in bracketed-args.

So the code above using return args ideally would have been:

!loc
!rot
actor_eyes_view_point(;loc rot)

[Also note that arguments in SkoookumScript do not need comma , delimiters - though you can use them if you think they help with readability.]

Since the bindings generated from Unreal (from the meta tags in C++ that are also used by the Blueprint system) don’t have the concept of return arguments they use just the traditional values that must be first passed in, modified and then used after the call.

Any custom methods/coroutines we make will use return arguments when appropriate and we encourage you to use them in your own custom routines too.


#7

Hi Noolarch,
I think all SkookumScript arguments are passing by reference already, aren’t they? If that’s true, what’s the use case of return-args?

BTW, it would be great that there’ll be code snippets beside each syntax item on the document page.


#8

GreatGuru, thanks for the tip!

I modified the binding generator to assign back value to any argument has CPF_OutParm property flag, and tested the AActor::GetActorEyesViewPoint example, now the loc and rot updated in SkookumScript side as expected.


#9

Yes - all SkookumScript arguments are passed by reference.

The benefit of return arguments is that you don’t need a pre-existing object to assign a value to. You just need to set a return argument before the end of a routine and the variable that was used in the call will be bound to the return argument object.

[The return argument syntax will also soon be updated so that you can declare a variable !var right in the result argument. So the below is using this somewhat newer syntax.]

Here is what the call looks like using (syntax updated) return arguments:

actor_eyes_view_point(;!loc !rot)

Here is what it looks like using pass by reference objects (assuming their default constructors are in place):

!loc: Vector3!
!rot: RotationAngles!
actor_eyes_view_point(loc rot)

Not too bad but I prefer the return argument syntax.

Code Snippet Examples

As for the code snippet examples - yes! These are coming.

A tiny few of the syntax production labels have links to document pages and the plan is that they all will.

Until and after then please continue to post language any language questions you may have in the Language and Compiling category.


Great curated posts to learn about SkookumScript
#10

Note: The vector math default construction issue has been fixed in the SkookumScript-UnrealEngine repo branch 4.8 on GitHub. All the VectorMath classes now properly intialize to zero. So you can just say Vector3! if you need a zero vector.


#11

Thanks for the CPF_OutParm fix Nate! Please post a pull request and we’ll integrate it back.


#12

Done! Check PR here.

BTW, where is the coding style of SkookumScript come from? I would suspect it 's from some kind of ancient mystic language :slight_smile: