Download

TFieldIterator Reflection with structs?

Hi, I’m trying to iterate through struct properties however I can’t seem to get the value. It expects a UObject, but my values are coming from a struct so how do I do this?


      
        FStructData* data = new FStructData();
        for (TFieldIterator<UProperty> prop(data->StaticStruct()); prop; ++prop){

            UNumericProperty* num = Cast<UNumericProperty>(*prop);
            if (num) {
                void* ValuePtr = num->ContainerPtrToValuePtr<void>(data->StaticStruct());

                //This line crashes
                float floatValue = num->GetSignedIntPropertyValue(ValuePtr);
            }
        }


I can’t figure out what to put inside GetSignedIntPropertyValue, I’ve tried tons of different things with GetSignedIntPropertyValue and ContainerPtrToValuePtr but they all crash the editor. Ideas?

Thanks!

So, as per Epic’s definition, the method is



/**
    * Gets the value of a signed integral property type
    * @param Data - pointer to property data to get
    * @return Data as a signed int
**/
int64 UNumericProperty::GetSignedIntPropertyValue(void const* Data) const
{
    check(0);
    return 0;
}


which makes me think that the floatValue might be declared as



 int64 floatValue = num->GetSignedIntPropertyValue(ValuePtr); 

Maybe the typecast is crashing?

But what is ValuePtr supposed to be? I just randomly tossed all kinds of stuff in there. Everything works perfectly except when GetSignedPropertyValue.

I’ve also tried with UFloatProperty, where that function is prob overridden with proper data but nothing works!

You mean GetSignedIntPropertyValue.
As per Epic’s usage it seems to be void pointer, for instance here (PyGenUtil.cpp)


const void* PropArrValue = (InProp->ElementSize * ArrIndex);

or uint8 pointer, for instance here (OnlineHotfixManager.cpp)


uint8* RowData = DataTableRowProperty->ContainerPtrToValuePtr<uint8>(DataTableRow, 0);

and you get the gist!

Got it working thanks to OnlineHotfixManager.cpp, thanks The-Cowboy!

Turns out ContainerPtrToValuePtr required a table row, so this won’t work with just structs. (Which is fine as I wanted it for a table anyway!)

Below gets the numeric values from the data table struct. From here it’s easy to add the rest of the value types!
(Note: ints and floats are not interchangable here and crash the editor if not properly separated)



        if (DataTable != nullptr)
        {
            //Get data from first row
            TArray<FName> names = DataTable->GetRowNames();
            FTableRowBase* DataTableRow = DataTable->FindRow<FTableRowBase>(names[0], "");

            for (TFieldIterator<UProperty> prop(DataTable->GetRowStruct()); prop; ++prop) {

                //Get property and data from first row
                UProperty* DataTableRowProperty = *prop;
                uint8* RowData = DataTableRowProperty->ContainerPtrToValuePtr<uint8>(DataTableRow, 0);

                if (DataTableRowProperty && DataTableRow && RowData) {

                    // See what type of property this is.
                    UNumericProperty* NumProp = Cast<UNumericProperty>(DataTableRowProperty);

                    if (NumProp){
                        //Make sure to differentiate between int and float
                        if (NumProp->IsInteger()) {
                            NumProp->GetSignedIntPropertyValue(RowData);
                        }
                        else {
                            NumProp->GetFloatingPointPropertyValue(RowData);
                        }
                    }
                }

            }
        }