Search code examples
c++.netclrcoreclrimetadataimport

Obtaining property values of a class using GetFieldProps


I am trying to obtain the values of the fields in a class using GetFieldProps

Initially I use GetClassLayout to get an array of FieldDef tokens, then enumerate them using GetFieldProps.

The result of each GetFieldProps call returns S_OK and does populate the name of the field in szField.

I am calling trying this in an ExceptionThrown callback, and when attempting this for the exception, it returns field names of _className, _message etc., but ppValue is always empty, as is pcchValue.

How do I get the value of fields in a class?

This is a sample of my current approach (with declarations etc. removed):

COR_FIELD_OFFSET* fieldTokensAndOffsets = new COR_FIELD_OFFSET[fieldArraySize];
m_info->GetClassLayout(
    classId,
    fieldTokensAndOffsets,
    fieldArraySize,
    &a,  
    &b);


for (int i = 0; i < fieldArraySize - 1; i++) {

    auto rid = fieldTokensAndOffsets[i].ridOfField;

    MetaDataImport->GetFieldProps(
        rid,
        &mb,
        fieldName,
        100,,
        &pchField,
        &pdwAttr,
        &ppvSigBlob,
        &pcbSigBlob,
        &pdwCPlusTypeFlag,
        &pValue,
        &pcchValue
    );
}

Solution

  • GetFieldProps only provides static information, so pValue & pcchValue are probably only relevant for fields representing constants.

    To get the actual value from an instance, I believe you need to use the COR_FIELD_OFFSET.ulOffset returned by GetClassLayout to get the memory location relative to the ObjectID (ObjectID is a pointer to the actual instance) and you can get the required size/interpretation by parsing the signature that GetFieldProps stores in ppvSigBlob and pcbSigBlob (the format of which is defined in ECMA-335 Partition II Section 23.2.4).

    • If the type is a primitive value type, then the size and interpretation should be self evident (eg. Int32 will be a 4 byte integer).
    • If the type is a reference type, then it will be a native int sized field containing the ObjectID.
    • If the type is an enum, then it will have the size of it's underlying type (ECMA-335 Partition II Section 14.3).
    • If the type is a non-primitive type, then you can use GetClassLayout to find the location of it's component fields.
    • you can get a further break-down of strings and arrays using GetStringLayout and GetArrayObjectInfo respectfully.