Swift底層原理-Mirror
反射:是指可以動態(tài)獲取類型、成員信息,在運行時可以調(diào)用方法、屬性等行為的特性。
對于一個純swift類來說,并不支持直接像
OC runtime那樣的操作,但是swift標(biāo)準(zhǔn)庫依舊提供了反射機制,用來訪問成員信息,即Mirror在使?
OC開發(fā)時很少強調(diào)其反射概念,因為OC的Runtime要?其他語?中的反射強?的多。但是Swift是??類型 安全的語?,不?持我們像OC那樣直接操作,它的標(biāo)準(zhǔn)庫仍然提供了反射機制來讓我們訪問成員信息。
Mirror簡介
-
Mirror是Swift中的反射機制的實現(xiàn),它的本質(zhì)是一個結(jié)構(gòu)體。
public struct Mirror {
/// The static type of the subject being reflected.
///
/// This type may differ from the subject's dynamic type when this mirror
/// is the `superclassMirror` of another mirror.
public let subjectType: Any.Type
/// A collection of `Child` elements describing the structure of the
/// reflected subject.
// public typealias Children = AnyCollection<Mirror.Child>
/*
public enum DisplayStyle : Sendable {
case `struct`
case `class`
case `enum`
case tuple
case optional
case collection
case dictionary
case set
}
*/
public let children: Mirror.Children
/// A suggested display style for the reflected subject.
public let displayStyle: Mirror.DisplayStyle?
/// A mirror of the subject's superclass, if one exists.
public var superclassMirror: Mirror? { get }
// 省略部分方法
}
-
subjectType:表示類型,被反射主體的類型 -
children:子元素集合 -
displayStyle:顯示類型,基本類型為nil -
superclassMirror:父類反射, 沒有父類為nil
Mirror簡單使用
- 我們通過
Mirror打印對象的屬性名稱和值
class Test {
var age: Int = 18
var name: String = "ssl"
}
var t = Test()
var mirror = Mirror(reflecting: t.self)
print("對象類型:\(mirror.subjectType)")
print("對象屬性個數(shù):\(mirror.children.count)")
print("對象的屬性及屬性值")
for child in mirror.children {
print("\(child.label!)---\(child.value)")
}
- 打印結(jié)果
對象類型:Test
對象屬性個數(shù):2
對象的屬性及屬性值
age---18
name---ssl
Mirror源碼
為什么通過
Mirror就可以獲得對象的屬性信息?我們通過源碼來探索它做了哪些事情在源碼中找到
Mirror.swift,快速定位到Mirror的初始化方法,如下:
public init(reflecting subject: Any) {
if case let customized as CustomReflectable = subject {
self = customized.customMirror
} else {
self = Mirror(internalReflecting: subject)
}
}
- 在初始化函數(shù)中判斷
subject是否遵守CustomReflectable協(xié)議,遵守協(xié)議的實例,直接調(diào)用customMirror屬性。 - 如果沒有遵守該協(xié)議,則走默認(rèn)初始化流程
Mirror(internalReflecting: subject)。
初始化
internal init(internalReflecting subject: Any,
subjectType: Any.Type? = nil,
customAncestor: Mirror? = nil)
{
// 1. 判斷實例對象的類型,如果為nil,則通過_getNormalizedType去獲取
let subjectType = subjectType ?? _getNormalizedType(subject, type: type(of: subject))
// 2. 獲取成員變量
let childCount = _getChildCount(subject, type: subjectType)
let children = (0 ..< childCount).lazy.map({
getChild(of: subject, type: subjectType, index: $0)
})
self.children = Children(children)
// 3. 獲取父類的Mirror
self._makeSuperclassMirror = {
guard let subjectClass = subjectType as? AnyClass,
let superclass = _getSuperclass(subjectClass) else {
return nil
}
// Handle custom ancestors. If we've hit the custom ancestor's subject type,
// or descendants are suppressed, return it. Otherwise continue reflecting.
if let customAncestor = customAncestor {
if superclass == customAncestor.subjectType {
return customAncestor
}
if customAncestor._defaultDescendantRepresentation == .suppressed {
return customAncestor
}
}
return Mirror(internalReflecting: subject,
subjectType: superclass,
customAncestor: customAncestor)
}
// 4. 設(shè)置 displayStyle
let rawDisplayStyle = _getDisplayStyle(subject)
switch UnicodeScalar(Int(rawDisplayStyle)) {
case "c": self.displayStyle = .class
case "e": self.displayStyle = .enum
case "s": self.displayStyle = .struct
case "t": self.displayStyle = .tuple
case "\0": self.displayStyle = nil
default: preconditionFailure("Unknown raw display style '\(rawDisplayStyle)'")
}
// 5. 設(shè)置 subjectType 和 _defaultDescendantRepresentation
self.subjectType = subjectType
self._defaultDescendantRepresentation = .generated
}
}
- 在該方法中,主要做了一下幾件事:
- 獲取
subjectType,如果傳入的有值就使用傳入的值,否則就通過_getNormalizedType函數(shù)去獲取 - 通過
_getChildCount獲取childCount,然后獲取children,注意這里是懶加載的 - 針對父類
SuperclassMirror處理 - 最后會獲取并解析顯示的樣式,并設(shè)置
Mirror一些其他屬性。
- 獲取
_getNormalizedType
- 我們首先看一下,是如果獲取實例對象的類型
@_silgen_name("swift_reflectionMirror_normalizedType")
internal func _getNormalizedType<T>(_: T, type: Any.Type) -> Any.Type
- 函數(shù)上面使用了一個編譯字段
@_silgen_name,這個是Swift的一個隱藏符號,作?是將某個 C/C++ 函數(shù)直接映射為 Swift 函數(shù)。也就是我們在調(diào)用_getNormalizedType函數(shù)的時候,本質(zhì)上是在調(diào)用swift_reflectionMirror_normalizedType函數(shù)。
const Metadata *swift_reflectionMirror_normalizedType(OpaqueValue *value,
const Metadata *type,
const Metadata *T) {
return call(value, T, type, [](ReflectionMirrorImpl *impl) { return impl->type; });
}
template<typename F>
auto call(OpaqueValue *passedValue, const Metadata *T, const Metadata *passedType,
const F &f) -> decltype(f(nullptr))
{
const Metadata *type;
OpaqueValue *value;
std::tie(type, value) = unwrapExistential(T, passedValue);
if (passedType != nullptr) {
type = passedType;
}
// 這里是類似swift的閉包
// 非類類型的調(diào)用
auto call = [&](ReflectionMirrorImpl *impl) {
impl->type = type;
impl->value = value;
auto result = f(impl);
return result;
};
// 類類型的調(diào)用
auto callClass = [&] {
if (passedType == nullptr) {
// Get the runtime type of the object.
const void *obj = *reinterpret_cast<const void * const *>(value);
auto isa = _swift_getClass(obj);
// Look through artificial subclasses.
while (isa->isTypeMetadata() && isa->isArtificialSubclass()) {
isa = isa->Superclass;
}
passedType = isa;
}
#if SWIFT_OBJC_INTEROP
// If this is a pure ObjC class, reflect it using ObjC's runtime facilities.
// ForeignClass (e.g. CF classes) manifests as a NULL class object.
auto *classObject = passedType->getClassObject();
if (classObject == nullptr || !classObject->isTypeMetadata()) {
ObjCClassImpl impl;
return call(&impl);
}
#endif
// Otherwise, use the native Swift facilities.
ClassImpl impl;
return call(&impl);
};
// 通過傳入類型的kind來判斷,返回不同類型imp
switch (type->getKind()) {
case MetadataKind::Tuple: {
TupleImpl impl;
return call(&impl);
}
case MetadataKind::Struct: {
StructImpl impl;
return call(&impl);
}
case MetadataKind::Enum:
case MetadataKind::Optional: {
EnumImpl impl;
return call(&impl);
}
case MetadataKind::ObjCClassWrapper:
case MetadataKind::ForeignClass:
case MetadataKind::Class: {
return callClass();
}
case MetadataKind::Metatype:
case MetadataKind::ExistentialMetatype: {
MetatypeImpl impl;
return call(&impl);
}
case MetadataKind::Opaque: {
#if SWIFT_OBJC_INTEROP
// If this is the AnyObject type, use the dynamic type of the
// object reference.
if (type == &METADATA_SYM(BO).base) {
return callClass();
}
#endif
// If this is the Builtin.NativeObject type, and the heap object is a
// class instance, use the dynamic type of the object reference.
if (type == &METADATA_SYM(Bo).base) {
const HeapObject *obj
= *reinterpret_cast<const HeapObject * const*>(value);
if (obj->metadata->getKind() == MetadataKind::Class) {
return callClass();
}
}
LLVM_FALLTHROUGH;
}
/// TODO: Implement specialized mirror witnesses for all kinds.
default:
break;
// Types can't have these kinds.
case MetadataKind::HeapLocalVariable:
case MetadataKind::HeapGenericLocalVariable:
case MetadataKind::ErrorObject:
swift::crash("Swift mirror lookup failure");
}
// If we have an unknown kind of type, or a type without special handling,
// treat it as opaque.
OpaqueImpl impl;
return call(&impl);
}
-
該方法比較長,但是邏輯比較清晰。主要做了兩件事:
- 根據(jù)
kind來判斷實例的類型,從而拿到不同類型對應(yīng)的impl - 如果類型不是類類型,則調(diào)用非類的
call(&impl);類是調(diào)用callClass。
- 根據(jù)
最終通過閉包返回一個
ReflectionMirrorImpl類型的成員變量出去。
ReflectionMirrorImpl
ReflectionMirrorImpl有以下6個子類:
-
TupleImpl元組的反射 -
StructImpl結(jié)構(gòu)體的反射 -
EnumImpl枚舉的反射 -
ClassImpl類的反射 -
MetatypeImpl元數(shù)據(jù)的反射 -
OpaqueImpl不透明類型的反射
- 我們首先看一下
ReflectionMirrorImpl結(jié)構(gòu)
struct ReflectionMirrorImpl {
const Metadata *type;
OpaqueValue *value;
virtual char displayStyle() = 0;
virtual intptr_t count() = 0;
virtual intptr_t childOffset(intptr_t index) = 0;
virtual const FieldType childMetadata(intptr_t index,
const char **outName,
void (**outFreeFunc)(const char *)) = 0;
virtual AnyReturn subscript(intptr_t index, const char **outName,
void (**outFreeFunc)(const char *)) = 0;
virtual const char *enumCaseName() { return nullptr; }
#if SWIFT_OBJC_INTEROP
virtual id quickLookObject() { return nil; }
#endif
// For class types, traverse through superclasses when providing field
// information. The base implementations call through to their local-only
// counterparts.
virtual intptr_t recursiveCount() {
return count();
}
virtual intptr_t recursiveChildOffset(intptr_t index) {
return childOffset(index);
}
virtual const FieldType recursiveChildMetadata(intptr_t index,
const char **outName,
void (**outFreeFunc)(const char *))
{
return childMetadata(index, outName, outFreeFunc);
}
virtual ~ReflectionMirrorImpl() {}
};
- 里面包含了
metedata、count等一些信息。這里也可以理解,上面swift_reflectionMirror_normalizedType方法中,最終在call函數(shù)的閉包中返回了imp->type,把類型信息返回出去了 - 這里我們以結(jié)構(gòu)體子類為例子,查看它源碼
StructImpl
struct StructImpl : ReflectionMirrorImpl {
// 是否支持反射
bool isReflectable() {
const auto *Struct = static_cast<const StructMetadata *>(type);
const auto &Description = Struct->getDescription();
return Description->isReflectable();
}
// 表明是一個結(jié)構(gòu)體
char displayStyle() {
return 's';
}
// 屬性個數(shù)
intptr_t count() {
if (!isReflectable()) {
return 0;
}
auto *Struct = static_cast<const StructMetadata *>(type);
return Struct->getDescription()->NumFields;
}
// 屬性偏移值
intptr_t childOffset(intptr_t i) {
auto *Struct = static_cast<const StructMetadata *>(type);
if (i < 0 || (size_t)i > Struct->getDescription()->NumFields)
swift::crash("Swift mirror subscript bounds check failure");
// Load the offset from its respective vector.
return Struct->getFieldOffsets()[i];
}
// 屬性的信息
const FieldType childMetadata(intptr_t i, const char **outName,
void (**outFreeFunc)(const char *)) {
StringRef name;
FieldType fieldInfo;
std::tie(name, fieldInfo) = getFieldAt(type, i);
assert(!fieldInfo.isIndirect() && "indirect struct fields not implemented");
*outName = name.data();
*outFreeFunc = nullptr;
return fieldInfo;
}
AnyReturn subscript(intptr_t i, const char **outName,
void (**outFreeFunc)(const char *)) {
auto fieldInfo = childMetadata(i, outName, outFreeFunc);
auto *bytes = reinterpret_cast<char*>(value);
auto fieldOffset = childOffset(i);
auto *fieldData = reinterpret_cast<OpaqueValue *>(bytes + fieldOffset);
return copyFieldContents(fieldData, fieldInfo);
}
};
- 在該結(jié)構(gòu)內(nèi)提供了獲取屬性、屬性信息等一些方法
- 但是這些方法內(nèi)部,都是通過
StructMetadata的getDescription方法來獲取對應(yīng)的一些信息
Description
- 在
StructImpl中我們看到很多關(guān)于Description的代碼,看來這個Description存儲著很多信息,在獲取Description的時候是從StructMetadata通過getDescription()方法獲取到。 - 這里我們還是以研究結(jié)構(gòu)體的
metadata為例子
using StructMetadata = TargetStructMetadata<InProcess>;
-
StructMetadata是TargetStructMetadata的別名
TargetStructMetadata
template <typename Runtime>
struct TargetStructMetadata : public TargetValueMetadata<Runtime> {
using StoredPointer = typename Runtime::StoredPointer;
using TargetValueMetadata<Runtime>::TargetValueMetadata;
const TargetStructDescriptor<Runtime> *getDescription() const {
return llvm::cast<TargetStructDescriptor<Runtime>>(this->Description);
}
// The first trailing field of struct metadata is always the generic
// argument array.
/// Get a pointer to the field offset vector, if present, or null.
const uint32_t *getFieldOffsets() const {
auto offset = getDescription()->FieldOffsetVectorOffset;
if (offset == 0)
return nullptr;
auto asWords = reinterpret_cast<const void * const*>(this);
return reinterpret_cast<const uint32_t *>(asWords + offset);
}
bool isCanonicalStaticallySpecializedGenericMetadata() const {
auto *description = getDescription();
if (!description->isGeneric())
return false;
auto *trailingFlags = getTrailingFlags();
if (trailingFlags == nullptr)
return false;
return trailingFlags->isCanonicalStaticSpecialization();
}
const MetadataTrailingFlags *getTrailingFlags() const {
auto description = getDescription();
auto flags = description->getFullGenericContextHeader()
.DefaultInstantiationPattern->PatternFlags;
if (!flags.hasTrailingFlags())
return nullptr;
auto fieldOffset = description->FieldOffsetVectorOffset;
auto offset =
fieldOffset +
// Pad to the nearest pointer.
((description->NumFields * sizeof(uint32_t) + sizeof(void *) - 1) /
sizeof(void *));
auto asWords = reinterpret_cast<const void *const *>(this);
return reinterpret_cast<const MetadataTrailingFlags *>(asWords + offset);
}
static constexpr int32_t getGenericArgumentOffset() {
return sizeof(TargetStructMetadata<Runtime>) / sizeof(StoredPointer);
}
static bool classof(const TargetMetadata<Runtime> *metadata) {
return metadata->getKind() == MetadataKind::Struct;
}
};
- 我們在第一個方法可以看到,
TargetStructDescriptor類型的Description - 在本類沒有屬性相關(guān),我們?nèi)ニ母割?code>TargetValueMetadata查看一下
TargetValueMetadata
template <typename Runtime>
struct TargetValueMetadata : public TargetMetadata<Runtime> {
using StoredPointer = typename Runtime::StoredPointer;
TargetValueMetadata(MetadataKind Kind,
const TargetTypeContextDescriptor<Runtime> *description)
: TargetMetadata<Runtime>(Kind), Description(description) {}
/// An out-of-line description of the type.
TargetSignedPointer<Runtime, const TargetValueTypeDescriptor<Runtime> * __ptrauth_swift_type_descriptor> Description;
static bool classof(const TargetMetadata<Runtime> *metadata) {
return metadata->getKind() == MetadataKind::Struct
|| metadata->getKind() == MetadataKind::Enum
|| metadata->getKind() == MetadataKind::Optional;
}
ConstTargetMetadataPointer<Runtime, TargetValueTypeDescriptor>
getDescription() const {
return Description;
}
typename Runtime::StoredSignedPointer
getDescriptionAsSignedPointer() const {
return Description;
}
};
- 這里我們便找到了
Description屬性,它的類型是TargetValueTypeDescriptor,應(yīng)該是TargetStructDescriptor的父類。 -
getDescription()方法,在TargetStructMetadata是重寫的這個方法
TargetStructDescriptor
- 跳轉(zhuǎn)到
TargetStructDescriptor中后,我們可以看到
template <typename Runtime>
class TargetStructDescriptor final
: public TargetValueTypeDescriptor<Runtime>,
public TrailingGenericContextObjects<TargetStructDescriptor<Runtime>,
TargetTypeGenericContextDescriptorHeader,
/*additional trailing objects*/
TargetForeignMetadataInitialization<Runtime>,
TargetSingletonMetadataInitialization<Runtime>> {
// 省略部分方法
public:
using TrailingGenericContextObjects::getGenericContext;
using TrailingGenericContextObjects::getGenericContextHeader;
using TrailingGenericContextObjects::getFullGenericContextHeader;
using TrailingGenericContextObjects::getGenericParams;
/// The number of stored properties in the struct.
/// If there is a field offset vector, this is its length.
uint32_t NumFields;
/// The offset of the field offset vector for this struct's stored
/// properties in its metadata, if any. 0 means there is no field offset
/// vector.
uint32_t FieldOffsetVectorOffset;
// 省略部分方法
};
-
TargetValueTypeDescriptor是它的父類,也就是說不同類型description都繼承于TargetValueTypeDescriptor - 在該結(jié)構(gòu)中發(fā)現(xiàn)兩個屬性
-
NumFields主要表示結(jié)構(gòu)體中屬性的個數(shù),如果只有一個字段偏移量則表示偏移量的長度 -
FieldOffsetVectorOffset表示這個結(jié)構(gòu)體元數(shù)據(jù)中存儲的屬性的字段偏移向量的偏移量,如果是0則表示沒有
-
TargetValueTypeDescriptor
template <typename Runtime>
class TargetValueTypeDescriptor
: public TargetTypeContextDescriptor<Runtime> {
public:
static bool classof(const TargetContextDescriptor<Runtime> *cd) {
return cd->getKind() == ContextDescriptorKind::Struct ||
cd->getKind() == ContextDescriptorKind::Enum;
}
};
- 該類并沒有太多信息,我們繼續(xù)查看父類
TargetTypeContextDescriptor
template <typename Runtime>
class TargetTypeContextDescriptor
: public TargetContextDescriptor<Runtime> {
public:
/// The name of the type.
TargetRelativeDirectPointer<Runtime, const char, /*nullable*/ false> Name;
/// A pointer to the metadata access function for this type.
///
/// The function type here is a stand-in. You should use getAccessFunction()
/// to wrap the function pointer in an accessor that uses the proper calling
/// convention for a given number of arguments.
TargetRelativeDirectPointer<Runtime, MetadataResponse(...),
/*Nullable*/ true> AccessFunctionPtr;
/// A pointer to the field descriptor for the type, if any.
TargetRelativeDirectPointer<Runtime, const reflection::FieldDescriptor,
/*nullable*/ true> Fields;
bool isReflectable() const { return (bool)Fields; }
// 省略部分方法
};
- 我們可以得到該類繼承自
TargetContextDescriptor - 有
Name、AccessFunctionPtr、Fields三個屬性- 其中
name就是類型的名稱 -
AccessFunctionPtr是該類型元數(shù)據(jù)訪問函數(shù)的指針 -
Fields是一個指向該類型的字段描述符的指針
- 其中
TargetContextDescriptor
template<typename Runtime>
struct TargetContextDescriptor {
/// Flags describing the context, including its kind and format version.
ContextDescriptorFlags Flags;
/// The parent context, or null if this is a top-level context.
TargetRelativeContextPointer<Runtime> Parent;
// 省略部分方法
};
- 它是
descriptors的基類 - 有兩個屬性,分別是
Flags和Parent- 其中
Flags是描述上下文的標(biāo)志,包括它的種類和格式版本。 -
Parent是記錄父類上下文的,如果是頂級則為null
- 其中
總結(jié)
- 至此,我們就對結(jié)構(gòu)體的
Description的層級結(jié)構(gòu)基本就理清楚了,現(xiàn)總結(jié)如下:
[圖片上傳失敗...(image-133e7-1684500526636)]
Mirror獲取數(shù)據(jù)
到此我們對
Description分析基本很透徹了,那么我們就回到最開始的初始化,看看Mirror都是怎樣從Description取出相應(yīng)的值的。-
在初始化方法中,主要干了一下幾件事:
- 獲取
subjectType,如果傳入的有值就使用傳入的值,否則就通過_getNormalizedType函數(shù)去獲取 - 通過
_getChildCount獲取childCount,然后獲取children,注意這里是懶加載的 - 針對父類
SuperclassMirror處理 - 最后會獲取并解析顯示的樣式,并設(shè)置
Mirror一些其他屬性。
- 獲取
type
let subjectType = subjectType ?? _getNormalizedType(subject, type: type(of: subject))
@_silgen_name("swift_reflectionMirror_normalizedType")
internal func _getNormalizedType<T>(_: T, type: Any.Type) -> Any.Type
SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
const Metadata *swift_reflectionMirror_normalizedType(OpaqueValue *value,
const Metadata *type,
const Metadata *T) {
return call(value, T, type, [](ReflectionMirrorImpl *impl) { return impl->type; });
}
- 假設(shè)現(xiàn)在是結(jié)構(gòu)體類型,此時的
impl就是個StructImpl類型,所以這里的type是StructImpl父類ReflectionMirrorImpl的屬性type。
cout
let childCount = _getChildCount(subject, type: subjectType)
@_silgen_name("swift_reflectionMirror_count")
internal func _getChildCount<T>(_: T, type: Any.Type) -> Int
- 實際調(diào)用
swift_reflectionMirror_count方法
SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
intptr_t swift_reflectionMirror_count(OpaqueValue *value,
const Metadata *type,
const Metadata *T) {
return call(value, T, type, [](ReflectionMirrorImpl *impl) {
return impl->count();
});
}
- 仍然以結(jié)構(gòu)體為例,此時的
impl為StructImpl,內(nèi)部的count()函數(shù):
intptr_t count() {
if (!isReflectable()) {
return 0;
}
auto *Struct = static_cast<const StructMetadata *>(type);
return Struct->getDescription()->NumFields;
}
- 這里的
Struct就是個TargetStructMetadata類型 - 通過
getDescription()函數(shù)獲取到一個TargetStructDescriptor類型的Description - 然后取
NumFields的值就是我們要的count。
屬性名和屬性值
let children = (0 ..< childCount).lazy.map({
getChild(of: subject, type: subjectType, index: $0)
})
self.children = Children(children)
- 通過
getChild方式去獲取所有屬性
internal func getChild<T>(of value: T, type: Any.Type, index: Int) -> (label: String?, value: Any) {
var nameC: UnsafePointer<CChar>? = nil
var freeFunc: NameFreeFunc? = nil
let value = _getChild(of: value, type: type, index: index, outName: &nameC, outFreeFunc: &freeFunc)
let name = nameC.flatMap({ String(validatingUTF8: $0) })
freeFunc?(nameC)
return (name, value)
}
- 內(nèi)部調(diào)用了
_getChild方法
@_silgen_name("swift_reflectionMirror_subscript")
internal func _getChild<T>(
of: T,
type: Any.Type,
index: Int,
outName: UnsafeMutablePointer<UnsafePointer<CChar>?>,
outFreeFunc: UnsafeMutablePointer<NameFreeFunc?>
) -> Any
SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
AnyReturn swift_reflectionMirror_subscript(OpaqueValue *value, const Metadata *type,
intptr_t index,
const char **outName,
void (**outFreeFunc)(const char *),
const Metadata *T) {
return call(value, T, type, [&](ReflectionMirrorImpl *impl) {
return impl->subscript(index, outName, outFreeFunc);
});
}
- 這里我們可以看到是調(diào)用了
impl的subscript函數(shù),同樣以結(jié)構(gòu)體為例,我們在StructImpl中找到該函數(shù),源碼如下:
AnyReturn subscript(intptr_t i, const char **outName,
void (**outFreeFunc)(const char *)) {
auto fieldInfo = childMetadata(i, outName, outFreeFunc);
auto *bytes = reinterpret_cast<char*>(value);
auto fieldOffset = childOffset(i);
auto *fieldData = reinterpret_cast<OpaqueValue *>(bytes + fieldOffset);
return copyFieldContents(fieldData, fieldInfo);
}
- 先通過
childMetadata獲取到fieldInfo,其實這里就是獲取FieldType,也就是屬性名 - 通過
childOffset函數(shù)和index獲取到對于的偏移量,最后根據(jù)內(nèi)存偏移去到屬性值。
childMetadata
const FieldType childMetadata(intptr_t i, const char **outName,
void (**outFreeFunc)(const char *)) {
StringRef name;
FieldType fieldInfo;
std::tie(name, fieldInfo) = getFieldAt(type, i);
assert(!fieldInfo.isIndirect() && "indirect struct fields not implemented");
*outName = name.data();
*outFreeFunc = nullptr;
return fieldInfo;
}
- 通過調(diào)用
getFieldAt函數(shù)獲取屬性名稱
getFieldAt
static std::pair<StringRef /*name*/, FieldType /*fieldInfo*/>
getFieldAt(const Metadata *base, unsigned index) {
using namespace reflection;
// If we failed to find the field descriptor metadata for the type, fall
// back to returning an empty tuple as a standin.
auto failedToFindMetadata = [&]() -> std::pair<StringRef, FieldType> {
auto typeName = swift_getTypeName(base, /*qualified*/ true);
missing_reflection_metadata_warning(
"warning: the Swift runtime found no field metadata for "
"type '%*s' that claims to be reflectable. Its fields will show up as "
"'unknown' in Mirrors\n",
(int)typeName.length, typeName.data);
return {"unknown", FieldType(&METADATA_SYM(EMPTY_TUPLE_MANGLING))};
};
// 獲取元類型中的描述符,如果沒有返回null,否則返回Descriptor
auto *baseDesc = base->getTypeContextDescriptor();
if (!baseDesc)
return failedToFindMetadata();
// 通過調(diào)用get方法,內(nèi)部是base+offset,通過相對偏移拿到fields地址
auto *fields = baseDesc->Fields.get();
if (!fields)
return failedToFindMetadata();
// 從數(shù)組中通過下標(biāo)拿到對應(yīng)的字段
auto &field = fields->getFields()[index];
// 拿到字段名稱
auto name = field.getFieldName();
// Enum cases don't always have types.
if (!field.hasMangledTypeName())
return {name, FieldType::untypedEnumCase(field.isIndirectCase())};
auto typeName = field.getMangledTypeName();
SubstGenericParametersFromMetadata substitutions(base);
auto typeInfo = swift_getTypeByMangledName(MetadataState::Complete,
typeName,
substitutions.getGenericArgs(),
[&substitutions](unsigned depth, unsigned index) {
return substitutions.getMetadata(depth, index);
},
[&substitutions](const Metadata *type, unsigned index) {
return substitutions.getWitnessTable(type, index);
});
// If demangling the type failed, pretend it's an empty type instead with
// a log message.
if (!typeInfo.getMetadata()) {
typeInfo = TypeInfo({&METADATA_SYM(EMPTY_TUPLE_MANGLING),
MetadataState::Complete}, {});
missing_reflection_metadata_warning(
"warning: the Swift runtime was unable to demangle the type "
"of field '%*s'. the mangled type name is '%*s'. this field will "
"show up as an empty tuple in Mirrors\n",
(int)name.size(), name.data(),
(int)typeName.size(), typeName.data());
}
auto fieldType = FieldType(typeInfo.getMetadata());
fieldType.setIndirect(field.isIndirectCase());
fieldType.setReferenceOwnership(typeInfo.getReferenceOwnership());
return {name, fieldType};
}
- 在該方法中,主要做了以下幾件事:
- 通過
getTypeContextDescriptor獲取baseDesc,也就是我們說的Description - 通過
Fields.get()獲取到fields - 通過
getFields()[index]或取對應(yīng)的field - 通過
getFieldName()函數(shù)獲取到屬性名稱
- 通過
childOffset
- 分析完屬性名的獲取,看一下偏移量是如何獲取的
intptr_t childOffset(intptr_t i) {
auto *Struct = static_cast<const StructMetadata *>(type);
if (i < 0 || (size_t)i > Struct->getDescription()->NumFields)
swift::crash("Swift mirror subscript bounds check failure");
// Load the offset from its respective vector.
return Struct->getFieldOffsets()[i];
}
- 調(diào)用
TargetStructMetadata中的getFieldOffsets函數(shù)源碼如下:
const uint32_t *getFieldOffsets() const {
auto offset = getDescription()->FieldOffsetVectorOffset;
if (offset == 0)
return nullptr;
auto asWords = reinterpret_cast<const void * const*>(this);
return reinterpret_cast<const uint32_t *>(asWords + offset);
}
我們可以看到這里通過獲取
Description中的屬性,這里使用的屬性是FieldOffsetVectorOffset。獲取到偏移值后通過內(nèi)存偏移即可獲取到屬性值。
總結(jié)
至此我們對Mirror的原理基本探索完畢了,現(xiàn)在總結(jié)一下:
-
Mirror通過初始化方法返回一個Mirror實例 - 這個實例對象根據(jù)傳入對象的類型去對應(yīng)的
Metadata中找到Description - 在
Description可以獲取name也就是屬性的名稱 - 通過內(nèi)存偏移獲取到屬性值
- 還可以通過
numFields獲取屬性的個數(shù)