multiple output function both for BP and other C++ functions ?

Hello everyone

I am learning c++ for ue4, and I am struggling to understand the use of references

I want to create a function with mutliple output and use it both on Blueprints and other c++ functions.
So after reading multiple similar questions, I have this , but I can’t find a solution to use the same multiple output function both in blueprint and c++ ?


        void MO (int Index, int& X, int& Y);

        int useMO(int Index );


// to be usable both in blueprint and other c++ functions
void AtestActor::MO(int Index, int& X, int& Y) {

    X = Index / 1000;
    Y = Index - (X * 1000);


// test using it in another function
int AtestActor::useMO(int var1) {
    int X=0;
    int Y=0;
    multipleOutput(var1, &X, &Y);   // ----> this the point where I can't find a solution ? How do I use the outputs of the function MO ?
    return 0;

I get the error

'void AtestActor::MO(int,int &,int &)': cannot convert argument 2 from 'int *' to 'int &'

Inthis thread, it is suggested to use pointers instead of references, but then the MO function is not accepted as an UFunction.

Any help / explanations will be greatly appreciated.

int x = 0; // Defines a int variable x
int* xptr = &x; // Defines a pointer to the int variable x

So when you do MO(var1, &x, &y) you’re trying to pass pointers to X/Y. The proper format would be just MO(var1, X, Y); That’s what the error message is telling you. And you are correct, Blueprints do not support pointers to non-uobject types.

Thank you ! But reading many post on this forum I thought that using pointers ( MO(var1, &x, &y) ) was the only way to have blueprint function with multiple output ?
If not , what are the other ways ?
And if it is the only way to have multiple output nodes, how do you use them in C++ functions ?

Generally speaking, if you pass in a pointer or a reference to a function, you’re assuming that the function is going to potentially access and modify your object (especially if you pass by reference). You can prevent this with using the “const” keyword, which sort of creates a contract between the function developer and the function user (like, “I promise I won’t change this value if you give it to me”).

If you pass a variable by “value” instead, the app will create a copy of the object and all of its values and then pass in the copy. The original will not be touched. If you have an array of 1,000,000 elements, it obviously becomes a pretty expensive memory copy to duplicate an array of 1m objects, so commonly people will just pass in the memory address of the object instead of the object itself. A memory address is only 4 bytes on a 32bit system, 8 bytes on a 64 bit system, so it is much lighter to pass that around, right? Pointers and references kind of go hand in hand with each other. You can say that a reference is really just an “address” to an object, but not the object itself. To use the address, you need to know what kind of data it represents. Whether you have an address to an integer or a massive array, or a class, the address is always the same size. Commonly you’ll dereference an address (such as with a pointer), which means that you’re working with the address data instead of the address itself.

So in theory, you could pass in pointers or references to a function and the function can do a bunch of logic to read or modify the data, and in theory it would be a processed “output”. If you want to see multiple output nodes in a blueprint node, you can either pass in function parameters by reference, or pass in a struct which contains your variables. For reference, look at the “LineTrace()” function and how it passes an FHitResult struct as an output.

Thank you Slayemin. I think I got it.

Now if I make a function with multiple Blueprint output via reference ( void MO (int Index, int& X, int& Y) ) , then how can I use that same function inside another c++ function ?

Or do I have to make 2 versions of the function, one for use in BP, one for use in C++ ?

(may be my question is not clear ? I don’t know how to reformulate it differently…)

I don’t know why you got the impression that you needed to use pointers to get multiple outputs. Here are two examples:

   UFUNCTION(BlueprintCallable, Category = Example)
    void IntOutputTest(int32 InputValue, int32& OutputIntA, int32& OutputIntB);

    UFUNCTION(BlueprintCallable, Category = Example)
    void ActorOutputTest(AActor* InputValue, AActor*& OutActorA, AActor*& OutActorB);

And the source

void ASomeActorClass::IntOutputTest(int32 InputValue, int32& OutputIntA, int32& OutputIntB)
    OutputIntA= InputValue;
    OutputIntB = InputValue;

void ASomeActorClass::ActorOutputTest(AActor* InputValue, AActor*& OutActorA, AActor*& OutActorB)
    OutActorA = InputValue;
    OutActorB = InputValue;

That would create 2 blueprint callable functions that take a single input and copies it to 2 output variables. FWIW: Blueprint does support pointers to base types (int/float/etc). What you were probably seeing about pointers is that most of the time, people are looking to get actors returned which have to be pointers.

As for how you use it in C++ you use at like any other function.

int32 StorageA = 0;
int32 StorageB = 0;

IntOutputTest(24, StorageA, StorageB);
UE_LOG(MyLog, Log, TEXT("Should be [24 ] = %i, %i"), StorageA, StorageB);

Same goes for pointers to actors.

Thank you very much Joe, I think I got it.

My misunderstanding was probably that I thought that I should always use the IntOutputTest function with (&) - which caused compiling error when used in nested functions.
using your last code exemple it would have been :

void ASomeActorClass::someOtherFunction (){
   int32 StorageA = 0;
   int32 StorageB = 0;
   IntOutputTest(24, &StorageA, &StorageB);  // **** ERROR *****
   UE_LOG(MyLog, Log, TEXT("Should be [24 ] = %i, %i"), StorageA, StorageB);

Why this is an error , I still do not fully understand…

Anyway it works now and I learnt a lot if not all :slight_smile:

thanks again !

In your function call, you’re still appending the & to StorageA and StoargeB (notice my examples doesn’t). In your case “&StorageA” creates a pointer to StorageA and then tries to pass it by reference to IntOutputTest(). Except IntOutputTest() is looking for a reference to an int, not a reference to the pointer to an int so you get the error.

Thank you very much. I think I get it. I guess it needs time to get used to the concepts :slight_smile: