Swift进阶-类与结构体
Swift-函数派发
Swift进阶-属性
Swift进阶-指针
Swift进阶-内存管理
Swift进阶-TargetClassMetadata和TargetStructMetadata数据结构源码分析
Swift进阶-Mirror解析
Swift进阶-闭包
Swift进阶-协议
Swift进阶-泛型
Swift进阶-String源码解析
Swift进阶-Array源码解析
课前知识储备
-
AnyObject
代表 - 任意类的实例、类的类型、仅类遵守的协议
class Teacher {
var age = 18
}
var t = Teacher()
var t1: AnyObject = t // 类的实例对象
var t2: AnyObject = Teacher.self // 类的类型
// 协议只允许被类遵守
protocol MyProtocol: AnyObject {
}
extension Teacher: MyProtocol {
}
-
Any
:代表任意类型,包含function类型或者optional类型。
let array: [AnyObject] = [1, "aaa"] // 报错!Int是基本数据类型
let array: [Any] = [1, "aaa"] // 修改后写法
-
AnyClass
: 代表任意实例对象的类型
class Teacher {
var age = 18
}
var t: AnyClass = Teacher.self // 它属于Teacher.Type
-
type(of: T)
: 获取动态类型
let age = 10
// value静态类型是Any
func test(_ value: Any) {
print(type(of: value))
}
test(age) // Int
-
T.self
:如果T是实例对象,那T.self返回的是实例自己;如果T是类型,那T.self返回的是元类型。
class Teacher {
var age = 18
}
var t = Teacher()
var t1 = t.self // 返回的是 t
var t2 = t.self.self // 返回的是 t
var t3 = Teacher.self // 返回的是 Teacher的元类型
-
self
与Self
self的使用场景
class Teacher {
var age = 18
func test() {
print(self) // self是当前实例对象
}
static func test1() {
print(self) // Teacher类对象
}
}
Self的使用场景
1.作为方法的返回类型,Self指代返回当前类的对象
2.在协议中方法返回类型 ,Self指代返回遵循这个协议的类型的对象
3.可用于使用静态属性
class Teacher {
static let age = 18
func test() -> Self {
return self // 返回当前实例对象
}
}
class Person {
static let age = 18
let age1 = age
var age2 = age
lazy var age3 = Self.age
}
protocol MyProtocol {
func get() -> Self
}
一、Mirror的基本用法
反射就是可以动态获取 类型、成员信息,在运行时可调用方法、属性 等行为的特性。
基于原生Swift
使用Runtime
的诸多局限性,它的标准库提供了反射机制来让我们访问成员信息。
Swift
的反射机制是基于一个叫Mirror
的结构体来实现的。
class Teacher {
var age = 18
func teach() {
print("teach")
}
}
let t = Teacher()
let mirror = Mirror(reflecting: t)
for property in mirror.children {
print("\(property.label!): \(property.value)")
}
// age: 18
ps: 没有办法访问到当前的函数teach,如果想要访问函数,需要把函数定义成属性信息。
那我们可以简单地封装一下,得到一个对象的key-value:
// 调用函数直接得到一个对象的key-value
func getKeyValue(_ mirrorObj: Any) -> [String: Any] {
let mirror = Mirror(reflecting: mirrorObj)
guard !mirror.children.isEmpty else{ return mirrorObj }
var result: [String: Any] = [:]
for child in mirror.children{
if let key = child.label{
result[key] = test(child.value)
}else{
print("No Keys")
}
}
return result
}
然而我们还可以定义出更高级Mirror的封装
:
class Teacher {
var age: Int
var name: String
init(age: Int, name: String) {
self.age = age
self.name = name
}
}
enum JSONMapError: Error{
case emptyKey
case notConformProtocol
}
protocol JSONMap{
func jsonMap() throws -> Any
}
//rethrows
extension JSONMap{
func jsonMap() throws -> Any{
let mirror = Mirror(reflecting: self)
guard !mirror.children.isEmpty else{ return self }
var result: [String: Any] = [:]
for child in mirror.children{
if let value = child.value as? JSONMap{
if let key = child.label{
result[key] = try? value.jsonMap()
}else{
return JSONMapError.emptyKey
}
}else{
return JSONMapError.notConformProtocol
}
}
return result
}
}
extension Teacher: JSONMap{}
extension Int: JSONMap{}
extension String: JSONMap{}
// 使用:
var t = Teacher(age: 18, name: "安老师")
do {
try t.jsonMap()
} catch {
print(error)
}
二、Mirror源码解析
打开Swift源码搜索到Mirror.swift
,很快清晰地发现Mirror是一个结构体,快速定位到初始化函数:
public init(reflecting subject: Any) {
if case let customized as CustomReflectable = subject {
self = customized.customMirror
} else {
self = Mirror(internalReflecting: subject)
}
}
首先看到初始化函数接收一个 Any
参数 subject
。要么subject是遵循 CustomReflectable
协议,如果是则调用 customized.customMirror
得到Mirror对象,要么去创建Mirror。
我们来看一下CustomReflectable
协议具体用法:
class Teacher: CustomReflectable {
var age: Int
var name: String
init(age: Int, name: String) {
self.age = age
self.name = name
}
var customMirror: Mirror{
let info = KeyValuePairs<String, Any>.init(dictionaryLiteral: ("age", age),("name", name))
let mirror = Mirror.init(self, children: info, displayStyle: .class, ancestorRepresentation: .generated)
return mirror
}
}
当实现这个 CustomReflectable
最直观的区别在与我们在 lldb debug
中会出现更详细的 debug 信息:
没有实现这个协议的时候就会只打印地址。
了解完CustomReflectable
就需要往下了解Mirror的初始化方法 Mirror(internalReflecting: subject)
,全局搜索一下Mirror(internalReflecting:
找到在 ReflectionMirror.swift
找到_getNormalizedType
在哪里声明的
编译器字段@_silgen_name
是swift的一个隐藏符号,作用是将某个c/c++函数直接映射为swift函数。
番外知识举例 @_silgen_name
的使用:
1.新建一个 C file 文件,取名为TestC
2.在TestC.c写一个C函数实现
#include "TestC.h"
int c_add(int a, int b) {
return a + b;
}
3.在.swift 文件声明一个映射函数
@_silgen_name("c_add")
func swift_add(a: Int32, b: Int32) -> Int32
4.直接调用 swift_add
var value = swift_add(a: 10, b: 20)
print(value)
再回到 Mirror初始化源码
里边,在获取subject的真实类型信息的时候,调用了_getNormalizedType
,而源码里这个函数的声明看出,实际上这个函数是在调用 swift_reflectionMirror_normalizedType
函数.
找到ReflectionMirror.cpp
里边的函数名为swift_reflectionMirror_normalizedType
:
// 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; });
}
它调用了一个 call函数(它返回了一个闭包),当前呢调用了call函数返回了类型信息。
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;
}
auto call = [&](ReflectionMirrorImpl *impl) {
impl->type = type;
impl->value = value;
auto result = f(impl);
return result;
};
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);
};
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();
}
}
SWIFT_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);
}
} // end anonymous namespace
可以看到call函数体里面return
之前使用switch做了一系列的类型判断,来确定返回是call回调
还是callClass回调
而最终所有的结果信息(type、value) 都是由当前的 ReflectionMirrorImpl
这个结构体去实现的。
看看switch里面怎么做判断的:
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();
}
}
SWIFT_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);
}
判断类型如果是 Tuple
则返回TupleImpl
,如果是Struct
则返回StructImpl
等...
那如果想反射不同类型的信息,就要把要反射的类型去继承这个ReflectionMirrorImpl
抽象结构体,提供具体的类型信息。
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;
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() {}
};
EnumImpl
的源码声明:
// Implementation for enums.
struct EnumImpl : ReflectionMirrorImpl {
//是否能反射
bool isReflectable() {
//做一个metadata的强转
const auto *Enum = static_cast<const EnumMetadata *>(type);
//找到metadata的Description
const auto &Description = Enum->getDescription();
//根据Description中的isReflectable字段来判断是否可以反射
return Description->isReflectable();
}
const char *getInfo(unsigned *tagPtr = nullptr,
const Metadata **payloadTypePtr = nullptr,
bool *indirectPtr = nullptr) {
// 'tag' is in the range [0..NumElements-1].
unsigned tag = type->vw_getEnumTag(value);
StringRef name;
FieldType info;
//获取FieldDescriptor的信息,也就是属性信息存放的地方
std::tie(name, info) = getFieldAt(type, tag);
const Metadata *payloadType = info.getType();
bool indirect = info.isIndirect();
if (tagPtr)
*tagPtr = tag;
if (payloadTypePtr)
*payloadTypePtr = payloadType;
if (indirectPtr)
*indirectPtr = indirect;
return name.data();
}
char displayStyle() override {
return 'e';
}
//获取count
intptr_t count() override {
if (!isReflectable()) {
return 0;
}
// No fields if reflecting the enumeration type instead of a case
if (!value) {
return 0;
}
const Metadata *payloadType;
//获取挂载类型,也就是Metadata
getInfo(nullptr, &payloadType, nullptr);
return (payloadType != nullptr) ? 1 : 0;
}
...
}
获取FieldDescriptor的信息是怎么获取的呢?
看看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))};
};
//获取TargetxxxDescriptor信息
auto *baseDesc = base->getTypeContextDescriptor();
if (!baseDesc)
return failedToFindMetadata();
//获取descriptor里的FieldDescriptor的信息
auto *fields = baseDesc->Fields.get();
if (!fields)
return failedToFindMetadata();
auto &field = fields->getFields()[index];
// Bounds are always valid as the offset is constant.
//获取属性的名称
auto name = field.getFieldName();
...
}
- 此时的源码可以分析出上一篇文章Swift进阶-属性通过
Mach-O
找到我们的属性名称是一致的。
Mirror
的工作原理:可以看出Mirro
是通过Metadata
(当前类型的元数据)、getDescription
(当前类型的描述)、FieldDescription
(当前类型属性的描述)来实现的。
三、enum数据结构还原
来看源码全局搜索在Metadata.h
找到 TargetEnumMetadata
的源码:
/// The structure of type metadata for enums.
template <typename Runtime>
struct TargetEnumMetadata : public TargetValueMetadata<Runtime> {
using StoredPointer = typename Runtime::StoredPointer;
using StoredSize = typename Runtime::StoredSize;
using TargetValueMetadata<Runtime>::TargetValueMetadata;
const TargetEnumDescriptor<Runtime> *getDescription() const {
return llvm::cast<TargetEnumDescriptor<Runtime>>(this->Description);
}
// The first trailing field of enum metadata is always the generic
// argument array.
/// True if the metadata records the size of the payload area.
bool hasPayloadSize() const {
return getDescription()->hasPayloadSizeOffset();
}
/// Retrieve the size of the payload area.
///
/// `hasPayloadSize` must be true for this to be valid.
StoredSize getPayloadSize() const {
assert(hasPayloadSize());
auto offset = getDescription()->getPayloadSizeOffset();
const StoredSize *asWords = reinterpret_cast<const StoredSize *>(this);
asWords += offset;
return *asWords;
}
StoredSize &getPayloadSize() {
assert(hasPayloadSize());
auto offset = getDescription()->getPayloadSizeOffset();
StoredSize *asWords = reinterpret_cast<StoredSize *>(this);
asWords += offset;
return *asWords;
}
bool isStaticallySpecializedGenericMetadata() const {
auto *description = getDescription();
if (!description->isGeneric())
return false;
auto *trailingFlags = getTrailingFlags();
if (trailingFlags == nullptr)
return false;
return trailingFlags->isStaticSpecialization();
}
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 offset =
getGenericArgumentOffset() +
description->getFullGenericContextHeader().Base.getNumArguments() +
(hasPayloadSize() ? 1 : 0);
auto asWords = reinterpret_cast<const void *const *>(this);
return reinterpret_cast<const MetadataTrailingFlags *>(asWords + offset);
}
static constexpr int32_t getGenericArgumentOffset() {
return sizeof(TargetEnumMetadata<Runtime>) / sizeof(StoredPointer);
}
static bool classof(const TargetMetadata<Runtime> *metadata) {
return metadata->getKind() == MetadataKind::Enum
|| metadata->getKind() == MetadataKind::Optional;
}
};
using EnumMetadata = TargetEnumMetadata<InProcess>;
继承自TargetValueMetadata
:
/// The common structure of metadata for structs and enums.
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;
}
};
using ValueMetadata = TargetValueMetadata<InProcess>;
继承自TargetMetadata
:
template <typename Runtime>
struct TargetMetadata {
using StoredPointer = typename Runtime::StoredPointer;
/// The basic header type.
typedef TargetTypeMetadataHeader<Runtime> HeaderType;
constexpr TargetMetadata()
: Kind(static_cast<StoredPointer>(MetadataKind::Class)) {}
constexpr TargetMetadata(MetadataKind Kind)
: Kind(static_cast<StoredPointer>(Kind)) {}
#if SWIFT_OBJC_INTEROP
protected:
constexpr TargetMetadata(TargetAnyClassMetadataObjCInterop<Runtime> *isa)
: Kind(reinterpret_cast<StoredPointer>(isa)) {}
#endif
private:
/// The kind. Only valid for non-class metadata; getKind() must be used to get
/// the kind value.
StoredPointer Kind;
public:
/// Get the metadata kind.
MetadataKind getKind() const {
return getEnumeratedMetadataKind(Kind);
}
/// Set the metadata kind.
void setKind(MetadataKind kind) {
Kind = static_cast<StoredPointer>(kind);
}
protected:
const TargetAnyClassMetadata<Runtime> *getClassISA() const {
return reinterpret_cast<const TargetAnyClassMetadata<Runtime> *>(Kind);
}
void setClassISA(const TargetAnyClassMetadata<Runtime> *isa) {
Kind = reinterpret_cast<StoredPointer>(isa);
}
public:
/// Is this a class object--the metadata record for a Swift class (which also
/// serves as the class object), or the class object for an ObjC class (which
/// is not metadata)?
bool isClassObject() const {
return static_cast<MetadataKind>(getKind()) == MetadataKind::Class;
}
/// Does the given metadata kind represent metadata for some kind of class?
static bool isAnyKindOfClass(MetadataKind k) {
switch (k) {
case MetadataKind::Class:
case MetadataKind::ObjCClassWrapper:
case MetadataKind::ForeignClass:
return true;
default:
return false;
}
}
/// Is this metadata for an existential type?
bool isAnyExistentialType() const {
switch (getKind()) {
case MetadataKind::ExistentialMetatype:
case MetadataKind::Existential:
return true;
default:
return false;
}
}
/// Is this either type metadata or a class object for any kind of class?
bool isAnyClass() const {
return isAnyKindOfClass(getKind());
}
const ValueWitnessTable *getValueWitnesses() const {
return asFullMetadata(this)->ValueWitnesses;
}
const TypeLayout *getTypeLayout() const {
return getValueWitnesses()->getTypeLayout();
}
void setValueWitnesses(const ValueWitnessTable *table) {
asFullMetadata(this)->ValueWitnesses = table;
}
// Define forwarders for value witnesses. These invoke this metadata's value
// witness table with itself as the 'self' parameter.
#define WANT_ONLY_REQUIRED_VALUE_WITNESSES
#define FUNCTION_VALUE_WITNESS(WITNESS, UPPER, RET_TYPE, PARAM_TYPES) \
template<typename...A> \
_ResultOf<ValueWitnessTypes::WITNESS ## Unsigned>::type \
vw_##WITNESS(A &&...args) const { \
return getValueWitnesses()->WITNESS(std::forward<A>(args)..., this); \
}
#define DATA_VALUE_WITNESS(LOWER, UPPER, TYPE)
#include "swift/ABI/ValueWitness.def"
unsigned vw_getEnumTag(const OpaqueValue *value) const {
return getValueWitnesses()->_asEVWT()->getEnumTag(const_cast<OpaqueValue*>(value), this);
}
void vw_destructiveProjectEnumData(OpaqueValue *value) const {
getValueWitnesses()->_asEVWT()->destructiveProjectEnumData(value, this);
}
void vw_destructiveInjectEnumTag(OpaqueValue *value, unsigned tag) const {
getValueWitnesses()->_asEVWT()->destructiveInjectEnumTag(value, tag, this);
}
size_t vw_size() const {
return getValueWitnesses()->getSize();
}
size_t vw_alignment() const {
return getValueWitnesses()->getAlignment();
}
size_t vw_stride() const {
return getValueWitnesses()->getStride();
}
unsigned vw_getNumExtraInhabitants() const {
return getValueWitnesses()->getNumExtraInhabitants();
}
/// Allocate an out-of-line buffer if values of this type don't fit in the
/// ValueBuffer.
/// NOTE: This is not a box for copy-on-write existentials.
OpaqueValue *allocateBufferIn(ValueBuffer *buffer) const;
/// Get the address of the memory previously allocated in the ValueBuffer.
/// NOTE: This is not a box for copy-on-write existentials.
OpaqueValue *projectBufferFrom(ValueBuffer *buffer) const;
/// Deallocate an out-of-line buffer stored in 'buffer' if values of this type
/// are not stored inline in the ValueBuffer.
void deallocateBufferIn(ValueBuffer *buffer) const;
// Allocate an out-of-line buffer box (reference counted) if values of this
// type don't fit in the ValueBuffer.
// NOTE: This *is* a box for copy-on-write existentials.
OpaqueValue *allocateBoxForExistentialIn(ValueBuffer *Buffer) const;
// Deallocate an out-of-line buffer box if one is present.
void deallocateBoxForExistentialIn(ValueBuffer *Buffer) const;
/// Get the nominal type descriptor if this metadata describes a nominal type,
/// or return null if it does not.
ConstTargetMetadataPointer<Runtime, TargetTypeContextDescriptor>
getTypeContextDescriptor() const {
switch (getKind()) {
case MetadataKind::Class: {
if (Runtime::ObjCInterop) {
const auto cls = static_cast<const TargetClassMetadata<
Runtime, TargetAnyClassMetadataObjCInterop<Runtime>> *>(this);
if (!cls->isTypeMetadata())
return nullptr;
if (cls->isArtificialSubclass())
return nullptr;
return cls->getDescription();
} else {
const auto cls = static_cast<const TargetClassMetadata<
Runtime, TargetAnyClassMetadata<Runtime>> *>(this);
if (!cls->isTypeMetadata())
return nullptr;
if (cls->isArtificialSubclass())
return nullptr;
return cls->getDescription();
}
}
case MetadataKind::Struct:
case MetadataKind::Enum:
case MetadataKind::Optional:
return static_cast<const TargetValueMetadata<Runtime> *>(this)
->Description;
case MetadataKind::ForeignClass:
return static_cast<const TargetForeignClassMetadata<Runtime> *>(this)
->Description;
default:
return nullptr;
}
}
/// Get the class object for this type if it has one, or return null if the
/// type is not a class (or not a class with a class object).
const typename Runtime::template TargetClassMetadata<Runtime> *
getClassObject() const;
/// Retrieve the generic arguments of this type, if it has any.
ConstTargetMetadataPointer<Runtime, swift::TargetMetadata> const *
getGenericArgs() const {
auto description = getTypeContextDescriptor();
if (!description)
return nullptr;
auto generics = description->getGenericContext();
if (!generics)
return nullptr;
auto asWords = reinterpret_cast<
ConstTargetMetadataPointer<Runtime, swift::TargetMetadata> const *>(this);
return asWords + description->getGenericArgumentOffset();
}
bool satisfiesClassConstraint() const;
const TypeContextDescriptor *getDescription() const;
bool isStaticallySpecializedGenericMetadata() const;
bool isCanonicalStaticallySpecializedGenericMetadata() const;
#if SWIFT_OBJC_INTEROP
/// Get the ObjC class object for this type if it has one, or return null if
/// the type is not a class (or not a class with a class object).
/// This is allowed for InProcess values only.
template <typename R = Runtime>
typename std::enable_if<std::is_same<R, InProcess>::value, Class>::type
getObjCClassObject() const {
return reinterpret_cast<Class>(
const_cast<TargetClassMetadata<
InProcess, TargetAnyClassMetadataObjCInterop<InProcess>> *>(
getClassObject()));
}
#endif
#ifndef NDEBUG
LLVM_ATTRIBUTE_DEPRECATED(void dump() const,
"Only meant for use in the debugger");
#endif
protected:
friend struct TargetOpaqueMetadata<Runtime>;
/// Metadata should not be publicly copied or moved.
constexpr TargetMetadata(const TargetMetadata &) = default;
TargetMetadata &operator=(const TargetMetadata &) = default;
constexpr TargetMetadata(TargetMetadata &&) = default;
TargetMetadata &operator=(TargetMetadata &&) = default;
};
TargetEnumMetadata
继承于 TargetValueMetadata
继承于 TargetMetadata
; 同时要注意 TargetRelativeDirectPointer
数据结构是相对地址信息 - 存储的是偏移量。(只粘贴了部分源码,自行下载源码看着分析就得出)
TargetEnumMetadata
的数据结构:
// 枚举Metadata
struct TargetEnumMetadata {
var kind: Int
var typeDescriptor: UnsafeMutablePointer<TargetEnumDescriptor>
}
// 枚举描述器
struct TargetEnumDescriptor {
var flags: Int32
var parent: TargetRelativeDirectPointer<UnsafeRawPointer>
var name: TargetRelativeDirectPointer<CChar>
var accessFunctionPointer: TargetRelativeDirectPointer<UnsafeRawPointer>
var fieldDescriptor: TargetRelativeDirectPointer<FieldDescriptor>
var NumPayloadCasesAndPayloadSizeOffset: UInt32
var NumEmptyCases: UInt32
}
// 相对地址信息
struct TargetRelativeDirectPointer<Pointee> {
var offset: Int32 // 存储偏移量
// 获取相对偏移指针
mutating func getmeasureRelativeOffset() -> UnsafeMutablePointer<Pointee>{
let offset = self.offset
return withUnsafePointer(to: &self) { p in
return UnsafeMutablePointer(mutating: UnsafeRawPointer(p).advanced(by: numericCast(offset)).assumingMemoryBound(to: Pointee.self))
}
}
}
// 属性描述器
struct FieldDescriptor {
var MangledTypeName: TargetRelativeDirectPointer<CChar>
var Superclass: TargetRelativeDirectPointer<CChar>
var kind: UInt16
var fieldRecordSize: Int16
var numFields: Int32 // 属性个数
var fields: FiledRecordBuffer<FieldRecord> // 属性列表
}
// 属性
struct FieldRecord {
var fieldRecordFlags: Int32 // flags
var mangledTypeName: TargetRelativeDirectPointer<CChar> // 属性类型
var fieldName: TargetRelativeDirectPointer<UInt8> // 属性名称
}
struct FiledRecordBuffer<Element>{
var element: Element
mutating func buffer(n: Int) -> UnsafeBufferPointer<Element> {
return withUnsafePointer(to: &self) {
let ptr = $0.withMemoryRebound(to: Element.self, capacity: 1) { start in
return start
}
return UnsafeBufferPointer(start: ptr, count: n)
}
}
mutating func index(of i: Int) -> UnsafeMutablePointer<Element> {
return withUnsafePointer(to: &self) {
return UnsafeMutablePointer(mutating: UnsafeRawPointer($0).assumingMemoryBound(to: Element.self).advanced(by: i))
}
}
}
注意:TargetRelativeDirectPointer
是相对地址信息,比如说TargetEnumDescriptor
里的name
存储的是相对于当前对象的偏移量,通过这个偏移量找到真实的内容。
那么我们设计出了Enum
的Metadata
,该如何使用呢?请看举例:
自定义一个枚举类 TerminalChar
enum TerminalChar {
case plain(Bool)
case bold
case empty
case cursor
}
通过按位转换成指针 UnsafeMutablePointer<TargetEnumMetadata>
,就可以对指针进行操作了(给个小案例叭,请自己运行看结果):
// 元类 Metadata
// var clazz = TerminalChar.self
// 使用按位转换成指针去操作(当前的元类clazz 就是 TargetEnumMetadata 这个结构体)
let enumMetadata_ptr = unsafeBitCast(TerminalChar.self as Any.Type, to: UnsafeMutablePointer<TargetEnumMetadata>.self)
let namePtr = enumMetadata_ptr.pointee.typeDescriptor.pointee.name.getmeasureRelativeOffset()
print(String(cString: namePtr)) // TerminalChar
print(enumMetadata_ptr.pointee.typeDescriptor.pointee.NumPayloadCasesAndPayloadSizeOffset) // 1
print(enumMetadata_ptr.pointee.typeDescriptor.pointee.NumEmptyCases) // 3
// 拿到属性描述器指针
let fieldDesc_ptr = enumMetadata_ptr.pointee.typeDescriptor.pointee.fieldDescriptor.getmeasureRelativeOffset()
print(String(cString: fieldDesc_ptr.pointee.MangledTypeName.getmeasureRelativeOffset()))
print(String(cString: fieldDesc_ptr.pointee.Superclass.getmeasureRelativeOffset()))
print(fieldDesc_ptr.pointee.kind) // 2
print(fieldDesc_ptr.pointee.fieldRecordSize) // 12
print(fieldDesc_ptr.pointee.numFields) // 4
print(String(cString: fieldDesc_ptr.pointee.fields.index(of: 0).pointee.fieldName.getmeasureRelativeOffset())) // plain
注意:
let enumMetadata_ptr = unsafeBitCast(clazz as Any.Type, to: UnsafeMutablePointer<TargetEnumMetadata>.self)
这句代码为什么一定要把TerminalChar.self
强转成Any.Type
?
unsafeBitCast
需要两个参数的内存大小相同。必须使用:TerminalChar.self as Any.Type
进行转换,因为根据测试发现TerminalChar.self
获取内存大小为0(这个地方是真的坑),先来看看MemoryLayout
输出结果:
番外小知识 unsafeBitCast
举例 :
var age = 10
var age1 = unsafeBitCast(age, to: Double.self)
print(age1) // 5e-323
注意:unsafeBitCast(age, to: Double.self)
中的age
是以二进制位的方式塞进Double
类型里边,本质上age1上存储的是0xa,当print(age1)的时候是输出科学技术的Double。来看看 x/8g 后的 age1:
言归正传!上面那个小案例可以把TerminalChar
enum类的属性输出出来了,试想一下,我们是不是可以从源码得出StructMetadata
,从而把一个结构体对象的属性内容打印出来。
如果你想学习ClassMetadata
、StructMetadata
和更详细的EnumMetadata
,可以查看我分享的这篇文章。