Context:
At some point in code, I want to get the value of struct (USTRUCT) which type is known at compile time, but during runtime I have only access to its UScriptStruct* and void* of its initialized memory adress.
Example:
With additional access to the FStructProperty of this struct (e.g. during call of CustomThunk from FFrame Stack), I could probably use something like this:
template<class T>
T GetStructValue(const FStructProperty* StructProperty, const void* StructContainer)
{
T StructValue = *StructProperty->ContainerPtrToValuePtr<T>(StructContainer);
return StructValue;
}
Where FStructProperty::ContainerPtrToValuePtr does the whole job.
My Problem:
As mentioned before, in my case I don’t have access to FStructProperty, and I’m only left with:
template<class T>
T GetStructValue(const UScriptStruct* StructType, const void* StructContainer)
{
/**
* How to find StructValue in this case?
*/
return StructValue;
}
Is there a way to do that with what I pass to this function (UScriptStruct*, void*)?
Can I somehow instantiate FStructProperty, or use any equivalent of FStructProperty::ContainerPtrToValuePtr which would work in this case?
I’m rookie when it comes to working on structs, FProperty’ies and Reflection data, so I’m probably missing something here. Please let me know in case more context or any other info is needed.
You don’t need an FStructProperty, void* StructContaineris the struct value.
All you can do is this (I recommend sticking with pointer rather than returning by value tho)
But this is essentially useless, just cast directly from calling code
FSomeStruct* SomeStruct = GetStructValue<FSomeStruct>(StructType, Container);
// same as this
FSomeStruct* SomeStruct = (FSomeStruct*)Container;
// if u really want to dereference to value
FSomeStruct SomeStruct = *(FSomeStruct*)Container;
In your first example there’s a misunderstanding - an FStructProperty describes the position of a struct within a larger container, like an UClass or another encompassing struct.
If that’s not the answer you are looking for, I’m gonna need more context to understand what you’re trying to do as it doesn’t make sense otherwise.
@Roy_Wierer.Seda145
The function won’t have access to any UPROPERTY of the desired type.
So this approach won’t work in my case.
Thank You however, it’s good to know that It could be done in such way.
@Chatouille
Yes, this… this works… I cannot believe it was already there, right in front of me, all the time…
I thought that memory initialized by UScriptStuct differs from the actual cpp type.
I’m shocked it actually works in this way, but I guess I’ll take it as it is
That explains a lot, much thanks!
One more quick question:
Why tho?
I expect this struct to be pretty small almost all the time. Is there an overhead that I’m missing? or some type safety concern?
Either way, thanks for help. I’m closing the thread.
Hmm, I see what you are doing, but it is a bit odd.
The only reason I could think of, that you would be doing this sort of thing, is if StructType was a derived struct type that you don’t know at compile time, and returning it as a base type which you do know. But you are doing check(StructType == T::StaticStruct()) which nullifies that statement. You DO know the struct type at compile time.
Maybe you have good reason to do so which eludes me, you don’t have to answer this question, but is there any reason you’re not simply doing this ?
template<class T>
T GetDecodedValue() const
{
T StructValue;
SetStructFromBinary(StructType, &StructValue, *this);
return StructValue;
}
However, I don’t want to spoil the whole idea behind it. At this point I’m just experimenting. I just need the most generic type that would be possible to store and replicate. I also need this to be blueprint friendly. This is why I’m using structs.
Not sure if this will work as I want it though.
That’s right and false at the same time. T GetDecodedValue() const is public and will possible to use outside of class.
I want the “gameplay coder” to define the type on his own by creating USTRUCT and by stroring it’s ::StaticStruct, but the the back-end code won’t know anything about it.
I’m just checking here for pure human error. e.g. If coder calls this function with float or void the code won’t compile. And if he calls it with wrong struct type, it will crash at runtime.
Actually NO. You are right here.
This is a leftover. I forgot I don’t have to use it anymore.
BUT I’ll have to use a similiar setup somewhere else to handle pure blueprint logic.
Hope this answers your curiosity.
Probably, there is indeed a beter way to do all this.