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).