Call Blueprint function from C++ and get the return value

**What I am trying to achieve: ** I am trying to call a blueprint function (if it exists) and get it’s return parameter. Essentially, I’d like to have a map of { “GetPlayer”, “ActualGetPlayerFunctionName” }. Now I am sure that you cannot store function pointers in an array or map, which would make this so much simpler.

I am calling


Testing

and returns a string with example text.



if (!IsValid(this))
{
    return;
}

UFunction* func = this->GetClass()->FindFunctionByName(FName("Testing"));

if (func == nullptr)
{
   GEngine->AddOnScreenDebugMessage(12332, 10.0, FColor::Red, "Could not find Function 'Testing'!");
   return;
}

FStructOnScope FuncParam(func);

FStrProperty* StrReturnValue = nullptr;

FString Value;

for (TFieldIterator<FProperty> It(func); It; ++It)
{
   FProperty* Prop = *It;


   if (Prop->HasAnyPropertyFlags(CPF_ReturnParm | CPF_OutParm))
   {
      GEngine->AddOnScreenDebugMessage(12332, 10.0, FColor::Red, "Found Return Value!");

      FStrProperty* StrProperty = CastField<FStrProperty>(Prop);

      if (StrProperty)
      {
         StrReturnValue = StrProperty;
      }
   }
}

this->ProcessEvent(func, FuncParam.GetStructMemory());

if (StrReturnValue != nullptr && IsValid(func))
{
   GEngine->AddOnScreenDebugMessage(12331, 10.0, FColor::Red, "StrReturnValue is valid!", false);

   Value = StrReturnValue->GetPropertyValue_InContainer(func);

   if (Value.IsEmpty())
   {
      GEngine->AddOnScreenDebugMessage(12331, 10.0, FColor::Red, "Value is Empty!", false);
   }
   else
   {
      FString Text = "Length of Value is: " + FString::FromInt(Value.Len());
      GEngine->AddOnScreenDebugMessage(12331, 10.0, FColor::Red, Text, false);

      UE_LOG(LogTemp, Warning, TEXT("%s"), *Value);
   }
}


So I can get the return property and cast it to a FStrProperty successfully. The problem is that I cannot access the value. This is where the documentation and source code is vague on the matter.

The source code describes


GetPropertyValue

as retrieving the value from an address, and


GetPropertyValue_InContainer

describes it as retrieving the value from a container.

I don’t understand where the value is stored, and how to get it. Shouldn’t the value be stored in the FStrProperty? (The blueprint function returns a string)

I keep getting access violation and GetOwner<UClass>() errors, and sometimes no error at all, but just garbage memory(Possible a memory leak).

I launched in DebugGame Editor and Visual Studio Debugger. The problem is accessing the value.

Thanks all,

2 Likes

Why not? I don’t know in what context to interpret that statement but you can absolutely do this in C++.

Regarding your other problem:
You can call Blueprint functions from C++ quite easily with UObject::CallFunctionByNameWithArguments.
However, I don’t think you can get the return value from this directly. The function eventually calls UObject::ProcessEvent with the function and the parsed command string as arguments. If you look into the source code for that I am pretty confident you could find out how to retrieve the return value as well.

If that doesn’t work out and you are pressed for time a less pretty solution would be to make your function that you call with UObject::CallFunctionByNameWithArguments cause some side effect that you can check afterwards for the result.

I am well aware that you can store function pointers in C++. However, to my understanding is that you cannot use function pointers with unreal engines reflection system.

I have been looking through the source code at things like FStrProperty, references to FProperties and so forth. The only thing I haven’t looked through the source code for is references to ProcessEvent. I will have a look tonight.

Surely you’d be able to get the return value from a blueprint function.

I feel kind of stupid now.



Value = StrReturnValue->GetPropertyValue_InContainer(FuncParam.GetStructMemory());


So at the end of UObject->ProcessEvent(UFunction, void*), Epic performs an FMemory::Memcpy, and copies all the out param values to the param memory address passed in, which in my case was FuncParam.GetStructMemory();



// Destroy local variables except function parameters.!! see also UObject::CallFunctionByNameWithArguments
// also copy back constructed value parms here so the correct copy is destroyed when the event function returns


This would be the obvious reason for getting the garbage memory from before, as I was pointing to the wrong memory address (func), when in fact, I was supposed to pass in the memory address of the container that actually contained the value (After ProcessEvent took place).

I’m still pretty raw on memory.

Thanks for your help.

Thanks! This thread helped me a lot.

My code with inputs and return value:

FName UMATRemapLiveLink::GetRemappedCurveName(ULiveLinkRemapAsset* RemapAsset, const FName& InCurveName) const
{
	UFunction* Func_GetRemappedCurveName = RemapAsset->GetClass()->FindFunctionByName(FName("GetRemappedCurveName"));
	if (!Func_GetRemappedCurveName)
	{
		return NAME_None;
	}

	FStructOnScope FuncParam(Func_GetRemappedCurveName);

	// Set input properties
	FNameProperty* InProp = CastField<FNameProperty>(Func_GetRemappedCurveName->FindPropertyByName(TEXT("CurveName")));
	if (!InProp)
	{
		return NAME_None;
	}
	InProp->SetPropertyValue_InContainer(FuncParam.GetStructMemory(), InCurveName);

	// Call function
	RemapAsset->ProcessEvent(Func_GetRemappedCurveName, FuncParam.GetStructMemory());

	// Get return property
	FNameProperty* OutProp = CastField<FNameProperty>(Func_GetRemappedCurveName->GetReturnProperty());
	if (!OutProp)
	{
		return NAME_None;
	}

	return OutProp->GetPropertyValue_InContainer(FuncParam.GetStructMemory());
}
1 Like