*FProperty generated by "CustomThunk" parameter gives Assertion failed: GetOwner<UClass>() when running ContainerPtrToValuePtr()

Hi, I’ve been trying to create a BP node that takes a value of any type (wildcard node input) and returns a string representation that can be later used to rebuild the original value.

The node runs perfectly when I feed in variables that live on the Blueprint (created via BP Editor > My Blueprint > Variables > + )- however when feeding in the return value of another node, I get a runtime crash Assertion failed: GetOwner<UClass>().

I think the cause is that the values that gets generated during runtime dont live on the same UClass as Blueprint “Variables” - but I’m not sure how I can get the parent UObject of the FProperty given as a parameter to my “customThunk” function (people on Unreal Slackers told me I cant). - I’ve tried replacing PropOwner w various things here like:

  • ParameterProp->GetOwnerUObject()
  • ParameterProp->GetOwnerUObject()->GetOuter()
  • ParameterProp->GetUPropertyWrapper()
  • ParameterProp->GetUPropertyWrapper()->GetOuter()

but so far no luck.

One solution I was considering is creating a UObject class for each and every FProperty type (one for FString, one for uint32, one for float (etc)) and then somehow copying the value over to an instance of my new class (and then do whatever I need). But I cant even seem to get a memory adress that I can copy the value from.

This is what the crash looks like:

This is the source code:


UCLASS()
class /*-*/ UFastProperties : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
public:
	UFUNCTION(BlueprintPure, CustomThunk, meta = (DefaultToSelf = "VariableOwner", CustomStructureParam = "variable", keywords = "cast, convert", DisplayName = "Any to String", CompactNodeTitle = "->", BlueprintAutocast), Category = "Fast | Fast Properties")
		static FString Conv_AnyToString(UObject* VariableOwner, TFieldPath<FProperty> variable, bool isVariable); // @note See: https://docs.unrealengine.com/5.2/en-US/metadata-specifiers-in-unreal-engine/#:~:text=To%20declare%20a%20custom%20exec%20function%2C%20use%20the%20syntax%20DECLARE_FUNCTION(execMyFunctionName)%20where%20MyFunctionName%20is%20the%20name%20of%20the%20original%20function.
	DECLARE_FUNCTION(execConv_AnyToString);

};

DEFINE_FUNCTION(UFastProperties::execConv_AnyToString)
{
	// Extract parameters
	UObject* PropOwner;
	Stack.StepCompiledIn<FProperty>(&PropOwner);
	Stack.Step(Context, Z_Param__Result);
	FProperty* ParameterProp = Stack.MostRecentProperty;
	bool isVariable;
	Stack.StepCompiledIn<FProperty>(&isVariable);

	// Prep intermediate containers
	FString OUTpropertyAsString = FString(TEXT(""));
	void* parameterPropValPtr = ParameterProp->ContainerPtrToValuePtr<void>(PropOwner);

	// Convert to string
	ParameterProp->ExportTextItem(OUTpropertyAsString, parameterPropValPtr, nullptr, PropOwner, 0, nullptr);

	// Pass on execution to next node
	P_FINISH;
	P_NATIVE_BEGIN;
	* (FString*)Z_Param__Result = OUTpropertyAsString; // Set return value
	P_NATIVE_END;
}

Full trace:
[Assertion failed: GetOwner() File:C:\UE\UE_5.1\Engine\Source\Runtime\Co - Pastebin.com

Im not sure how to move forward from here, any insights would be highly appreciated. I should add that I’m also open for solutions that doesn’t involve customThunk (say by making a K2 node), as long as I have a wildcard input on my node and I can extract its value as text (say by running something like ContainerPtrToValuePtr (and then from there either copying the value onto a new object or running ExportTextItem directly) or equivalent on it) I’m happy. I would also be willing to read/write the bytes directly, but again - I don’t even know how to get the datas memory address currently (let alone its length).

Thanks for reading :sparkling_heart:

You don’t need OwnerObject or ContainerPtrToValuePtr.
You can extract both FProperty and value from the Stack after stepping.
OwnerObject is not required for ExportText, it’s not used in most implementations, it should work just fine with nullptr.

    UFUNCTION(BlueprintPure, CustomThunk, meta = (CustomStructureParam = "variable", keywords = "cast, convert", DisplayName = "Any to String", CompactNodeTitle = "->", BlueprintAutocast), Category = "Fast | Fast Properties")
    static FString Conv_AnyToString(int Variable);
    DECLARE_FUNCTION(execConv_AnyToString);

DEFINE_FUNCTION(UFastProperties::execConv_AnyToString)
{
    Stack.StepCompiledIn<FProperty>(NULL);
    FProperty* Prop = Stack.MostRecentProperty;
    void* ValPtr = Stack.MostRecentPropertyAddress;
    P_FINISH;
    P_NATIVE_BEGIN;
    Prop->ExportTextItem_Direct(*(FString*)Z_Param__Result, ValPtr, nullptr, nullptr, 0, nullptr);
    P_NATIVE_END;
}
3 Likes

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.