Swift之深入解析反射Mirror的底层原理
Posted Forever_wj
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Swift之深入解析反射Mirror的底层原理相关的知识,希望对你有一定的参考价值。
一、Mirror 的底层分析
① 反射 API
- 反射 API 由两部分实现:
-
- 一部分是通过 Swift 实现,即 ReflectionMirror.swift;
-
- 一部分是通过 C++ 实现,即 ReflectionMirror.mm;
- 两者之间是通过暴露给 Swift 的 C++ 函数进行通信,即 @_silgen_name 修饰符会通知 Swift 编译器将这个 Swift 函数映射成 C++ 函数的符号;
- 使用 @_silgen_name 关键字声明的方法,实际调用是括号中的方法,例如 swift_ydw_add 实际调用的是 c 中的 ydw_add;
- 通过 C 定义一个方法,在 Swift 中使用:
// 定义c方法
// .h声明
int ydw_add(int a, int b);
// .c中实现
int ydw_add(int a, int b){
return a+b;
}
// 桥接文件中引入头文件
#import "test.h"
// swift 使用
var value = ydw_add(10, 20)
print(value)
// 打印结果
30
- 可以将上述代码中的“桥接文件中引入头文件”更改为采用 @_silgen_name 关键字的方式:
// swift中针对ydw_add方法的声明
// 通过@_silgen_name声明
@_silgen_name("ydw_add")
func swift_ydw_add(_ a: Int32, _ b: Int32) -> Int32
// 使用
var value = swift_cjl_add(20, 30)
print(value)
// 打印结果
50
② Mirror
- Mirror 的源码是在 Mirror.swift 文件中,路径为 swift->stdlib->public->core->Mirror.swift。
- 在 Mirror.swift 文件中找到 Mirror,可以看到它是一个结构体类型:
public struct Mirror {
/// Representation of descendant classes that don't override
/// `customMirror`.
///
/// Note that the effect of this setting goes no deeper than the
/// nearest descendant class that overrides `customMirror`, which
/// in turn can determine representation of *its* descendants.
internal enum _DefaultDescendantRepresentation {
/// Generate a default mirror for descendant classes that don't
/// override `customMirror`.
///
/// This case is the default.
case generated
/// Suppress the representation of descendant classes that don't
/// override `customMirror`.
///
/// This option may be useful at the root of a class cluster, where
/// implementation details of descendants should generally not be
/// visible to clients.
case suppressed
}
- 查找其初始化方法 public init(reflecting subject: Any):
public init(reflecting subject: Any) {
// 判断 subject 是否符合 CustomReflectable 动态类型
if case let customized as CustomReflectable = subject {
// 如果符合,则由 customMirror 确定属性
self = customized.customMirror
} else {
// 如果不符合,则由语言生成
self = Mirror(internalReflecting: subject)
}
}
- 查找 internalReflecting 方法(路径为 swift->stdlib->public->core->ReflectionMirror.swift),如下:
extension Mirror {
// Mirror的初始化器中检索需要的信息
/*
- subject 将要被反射的值
- subjectType 将要被反射的 subject 值的类型,通常是值的运行时类型
*/
internal init(internalReflecting subject: Any,
subjectType: Any.Type? = nil,
customAncestor: Mirror? = nil)
{
// 根据_getNormalizedType获取传入的subject的真正类型,其中type(of: subject)获取的动态类型
let subjectType = subjectType ?? _getNormalizedType(subject, type: type(of: subject))
// 获取属性大小
let childCount = _getChildCount(subject, type: subjectType)
// 遍历,将属性存储到字典中
let children = (0 ..< childCount).lazy.map({
// getChild函数时C++的_getChild 函数的简单封装,将标签名字中包含的C字符串转换为Swift字符串
getChild(of: subject, type: subjectType, index: $0)
})
// 赋值给Mirror的属性children
self.children = Children(children)
// 设置父类反射
self._makeSuperclassMirror = { // 按需求构建父类的Mirror的闭包
// 获取传入对象的类
guard let subjectClass = subjectType as? AnyClass,
// 获取父类
let superclass = _getSuperclass(subjectClass) else {
return nil // 非类的类型、没有父类的类的Mirror,会获取到nil
}
// 调用者可以用一个可作为父类的Mirror直接返回Mirror实例来指定自定义的祖先的表现
// 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
}
}
// 给相同值返回一个将 superclass作为 subjectType的新的Mirror
return Mirror(internalReflecting: subject,
subjectType: superclass,
customAncestor: customAncestor)
}
// 获取并解析显示的样式,并设置Mirror的其他属性
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)'")
}
self.subjectType = subjectType
self._defaultDescendantRepresentation = .generated
}
// 快速查找
internal static func quickLookObject(_ subject: Any) -> _PlaygroundQuickLook? {
#if _runtime(_ObjC)
let object = _getQuickLookObject(subject)
return object.flatMap(_getClassPlaygroundQuickLook)
#else
return nil
#endif
}
}
// superclassMirror属性的底层返回
public var superclassMirror: Mirror? {
return _makeSuperclassMirror()
}
nternal let _makeSuperclassMirror: () -> Mirror?
- internalReflecting 的流程分析:
-
- 通过 _getNormalizedType 获取传入的 subject 的真正类型;
-
- 通过 _getChildCount 方法获取类中的属性个数;
-
- 遍历属性,通过 getChild 方法(C++ 的 _getChild 函数的简单封装)将标签名字中包含的 C 字符串转换为 Swift 字符串,并将属性存储到字典中,赋值给 Mirror 的属性 children;
-
- Mirror 有一个属性 superclassMirror,会返回该类的父类,其底层是返回一个 _makeSuperclassMirror 属性,用于保存父类的 Mirror 闭包。首先会通过 subjectType 获取父类,然后按照需求构建父类的 Mirror 闭包,如果是非类的类型、没有父类的类的 Mirror,会获取到 nil。反之,则直接返回一个可作为父类的 Mirror 的实例对象。
-
- 获取并解析显示的样式,并设置 Mirror 的其它属性。
- 进入 _getNormalizedType 的实现,根据定义,最终会调用 C++ 中的 swift_reflectionMirror_normalizedType -> Call 方法:
@_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; });
}
/*
- passedValue 实际需要传入的swift的值的指针
- T 该值的静态类型
- passedType 被显式传入且会用在反射过程中的类型
- f 传递被查找到的会被调用的实现的对象引用
- 返回值:返回f参数调用时的返回值
*/
template<typename F>
auto call(OpaqueValue *passedValue, const Metadata *T, const Metadata *passedType,
const F &f) -> decltype(f(nullptr))
{
// 获取type
const Metadata *type;
OpaqueValue *value;
std::tie(type, value) = unwrapExistential(T, passedValue);
// 判断传入type是否为空,如果不为空,则直接赋值给type
if (passedType != nullptr) {
type = passedType;
}
// 使用 ReflectionMirrorImpl 子类的实例去结束调用f,然后会调用这个实例上的方法去真正的工作完成
auto call = [&](ReflectionMirrorImpl *impl) {
// 返回的type是传入非type
impl->type = type;
impl->value = value;
auto result = f(impl);
return result;
};
.....
switch (type->getKind()) {
case MetadataKind::Tuple: { // 元组
......
}
case MetadataKind::Struct: { // 结构体
......
}
case MetadataKind::Enum: // 枚举
case MetadataKind::Optional: { // 可选
......
}
......
}
// unwrapExistential实现
static std::tuple<const Metadata *, OpaqueValue *>
unwrapExistential(const Metadata *T, OpaqueValue *Value) {
// If the value is an existential container, look through it to reflect the
// contained value.如果该值是一个存在的容器,请查看它以反映包含的值。
// TODO: Should look through existential metatypes too, but it doesn't
// really matter yet since we don't have any special mirror behavior for
// concrete metatypes yet.
while (T->getKind() == MetadataKind::Existential) {
auto *existential
= static_cast<const ExistentialTypeMetadata *>(T);
// Unwrap the existential container.打开存在容器
T = existential->getDynamicType(Value);
Value = existential->projectValue(Value);
// Existential containers can end up nested in some cases due to generic
// abstraction barriers. Repeat in case we have a nested existential.
}
return std::make_tuple(T, Value);
}
// getDynamicType的实现
template<> const Metadata *
ExistentialTypeMetadata::getDynamicType(const OpaqueValue *container) const {
// 根据 获取此存在类型使用的表示形式 判断
switch (getRepresentation()) {
case ExistentialTypeRepresentation::Class: {
auto classContainer =
reinterpret_cast<const ClassExistentialContainer*>(container);
void *obj = classContainer->Value;
return swift_getObjectType(reinterpret_cast<HeapObject*>(obj));
}
case ExistentialTypeRepresentation::Opaque: {
auto opaqueContainer =
reinterpret_cast<const OpaqueExistentialContainer*>(container);
return opaqueContainer->Type;
}
case ExistentialTypeRepresentation::Error: {
const SwiftError *errorBox
= *reinterpret_cast<const SwiftError * const *>(container);
return errorBox->getType();
}
}
swift_runtime_unreachable(
"Unhandled ExistentialTypeRepresentation in switch.");
}
- call 中主要是一个 switch 声明和一些额外的逻辑去处理特殊的情况,主要是 ReflectionMirrorImpl 的子类实例去结束调用 f,然后会调用这个实例上的方法去让真正的工作完成。
- _getNormalizedType 的主要流程分析:
-
- 首先根据 unwrapExistential 获取 type 类型,其依赖于 metaData 元数据;
-
- 判断传入的 passedType 是否为空,如果不为空,则直接赋值给 type;
-
- 使用 ReflectionMirrorImpl 子类的实例去结束调用 f,然后会调用这个实例上的方法完成。
③ _getNormalizedType
- 运行 swift 源码,在 Call 函数的第一行加断点;
- 在源码终端依次输入下面代码:
class YDWTeacher {
var age = 18
}
var t = YDWTeacher()
let mirror = Mirror(reflecting: t)
- 程序会执行在 Call 的调用处,运行结果如下:
- 其中参数的调试结果说明:
-
- value 是 Mirror 实例;
-
- type 是 type(of:) 获取的类型;
-
- T 是自己传入的类型;
④ ReflectionMirrorImpl 反射基类
- ReflectionMirrorImpl 的种类如下:
-
- TupleImpl 元组的反射;
-
- StructImpl 结构体的反射;
-
- EnumImpl 枚举的反射;
-
- ClassImpl 类的反射;
-
- MetatypeImpl 元数据的反射;
-
- OpaqueImpl 不透明类型的反射;
- 以 Struct 的反射为例,首先查看 ReflectionMirrorImpl 的底层定义:
// Abstract base class for reflection implementations.
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;
//获取枚举的case名字
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() {}
};
- 继续进入 StructImpl 结构体的底层实现:
// Implementation for structs.
// ReflectionMirrorImpl 的子类 StructImpl 结构体反射
struct StructImpl : ReflectionMirrorImpl {
bool isReflectable() { // 是否支持反射
const auto *Struct = static_cast<const StructMetadata *>(type);
const auto &Description = Struct->getDescription();
return Description->isReflectable();
}
// 用 s 的显式样式来表明这是一个结构体
char displayStyle() {
return 's';
}
intptr_t count() {
if (!isReflectable()) {
return 0;
}
// 首先也是找到metadata,然后通过metadata找到desc,然后找到fields,即 NumFields 记录属性的count
auto *Struct = static_cast<const StructMetadata *>(type);
return Struct->getDescription()->NumFields;// 属性的count
}
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;
// 通过getFieldAt获取属性的名称
std::tie(name, fieldInfo) = getFieldAt(type, i);
assert(!fieldInfo.isIndirect() && "indirect struct fields not implemented");
*outName = name.data();
*outFreeFunc = nullptr;
return fieldInfo;
}
// subscript 用来获取当前属性的名称和值
AnyReturn subscript(intptr_t i, const char **outName,
void (**outFreeFunc)(const char *)) {
// 获取metaadata
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);
}
};
- 注意点:
- count 方法中属性个数的获取,是通过 metadata,然后找到其 desc,然后找到 NumFields 获取的,即 NumFields 记录属性的 count;
- subscript 方法主要用来获取当前属性的名称和值;
- 首先获取 metadata;
- 然后获取属性的偏移值 fieldOffset;
- 通过首地址+偏移值,计算属性存储的指针。
二、仿写 Mirror
① TargetStructMetadata 结构体:struct 反射类
- 从 Struct 的反射类 StructImpl 中可以知道,其 type 的类型是 StructMetadata:
// Implementation for structs.
struct StructImpl : ReflectionMirrorImpl {
bool isReflectable() {
const auto *Struct = static_cast<const StructMetadata *>(type);
const auto &Description = Struct->getDescription();
return Description->isReflectable();
}
char displayStyle() {
return 's';
}
intptr_t count() {
if iOS开发-Swift进阶之Mirror源码解析!