文档章节

swift class的虚函数表、扩展、@objc修饰、虚函数的派发方式研究

o
 osc_n6euf5h6
发布于 2019/03/19 19:34
字数 725
阅读 16
收藏 0

精选30+云产品,助力企业轻松上云!>>>

swift class的虚函数表、扩展、@objc修饰的研究

 

工具:

swiftc -emit-sil BaseClass.swift | xcrun swift-demangle > ClassFunc.silgen

cat ClassFunc.silgen

 

目标:

1、@objc和@objc dynamic修饰的函数是否进入虚函数表;

2、虚函数的的派发机制是什么?函数的调用在编译器层面最终转化为apply调用;

3、extension中的缺省修饰函数是否进入虚函数表;

4、extension中的@objc修饰函数的行为;

5、结构体是否允许@objc修饰:

@objc can only be used with members of classes, @objc protocols, and concrete extensions of classes

 

 

https://www.cnblogs.com/feng9exe/p/9460336.html

 

class NSObjectBase: NSObject {

    func Msg_Normal(){ print("Msg_Normal") }

    func Msg_Second(){ print("Msg_Second") }

    func Msg_Third(){ print("Msg_Second") }

    @objc func Msg_ObjcX(){}

    @objc dynamic func Msg_Objc_Dynamic(){}

    func callTest(){self.Msg_Normal()}

    func callAgain(){self.Msg_Third()}

}

 

extension NSObjectBase{

    @objc func OcExtensionFunc(){print("OcExtensionFunc")}

}

 

class DerivedOcClass:NSObjectBase{

    override func OcExtensionFunc(){print("DerivedOcClass OcExtensionFunc")}

}

 

// NSObjectBase.Msg_Objc_DynamicX()

sil hidden @NSObjectBase.NSObjectBase.Msg_Objc_DynamicX() -> () : $@convention(method) (@guaranteed NSObjectBase) -> () {

// %0                                             // user: %1

bb0(%0 : $NSObjectBase):

  debug_value %0 : $NSObjectBase, let, name "self", argno 1 // id: %1

  %2 = tuple ()                                   // user: %3

  return %2 : $()                                 // id: %3

} // end sil function 'NSObjectBase.NSObjectBase.Msg_Objc_DynamicX() -> ()'

 

// @objc NSObjectBase.Msg_Objc_DynamicX()

sil hidden [thunk] @@objc NSObjectBase.NSObjectBase.Msg_Objc_DynamicX() -> () : $@convention(objc_method) (NSObjectBase) -> () {

// %0                                             // users: %4, %3, %1

bb0(%0 : $NSObjectBase):

  strong_retain %0 : $NSObjectBase                // id: %1

  // function_ref NSObjectBase.Msg_Objc_DynamicX()

  %2 = function_ref @NSObjectBase.NSObjectBase.Msg_Objc_DynamicX() -> () : $@convention(method) (@guaranteed NSObjectBase) -> () // user: %3

  %3 = apply %2(%0) : $@convention(method) (@guaranteed NSObjectBase) -> () // user: %5

  strong_release %0 : $NSObjectBase               // id: %4

  return %3 : $()                                 // id: %5

} // end sil function '@objc NSObjectBase.NSObjectBase.Msg_Objc_DynamicX() -> ()'

 

// NSObjectBase.Msg_ObjcX()

sil hidden @NSObjectBase.NSObjectBase.Msg_ObjcX() -> () : $@convention(method) (@guaranteed NSObjectBase) -> () {

// %0                                             // user: %1

bb0(%0 : $NSObjectBase):

  debug_value %0 : $NSObjectBase, let, name "self", argno 1 // id: %1

  %2 = tuple ()                                   // user: %3

  return %2 : $()                                 // id: %3

} // end sil function 'NSObjectBase.NSObjectBase.Msg_ObjcX() -> ()'

 

// @objc NSObjectBase.Msg_ObjcX()

sil hidden [thunk] @@objc NSObjectBase.NSObjectBase.Msg_ObjcX() -> () : $@convention(objc_method) (NSObjectBase) -> () {

// %0                                             // users: %4, %3, %1

bb0(%0 : $NSObjectBase):

  strong_retain %0 : $NSObjectBase                // id: %1

  // function_ref NSObjectBase.Msg_ObjcX()

  %2 = function_ref @NSObjectBase.NSObjectBase.Msg_ObjcX() -> () : $@convention(method) (@guaranteed NSObjectBase) -> () // user: %3

  %3 = apply %2(%0) : $@convention(method) (@guaranteed NSObjectBase) -> () // user: %5

  strong_release %0 : $NSObjectBase               // id: %4

  return %3 : $()                                 // id: %5

} // end sil function '@objc NSObjectBase.NSObjectBase.Msg_ObjcX() -> ()'

 

 

 

 

sil hidden @NSObjectBase.NSObjectBase.callTest() -> () : $@convention(method) (@guaranteed NSObjectBase) -> () {

// %0                                             // users: %3, %2, %1

bb0(%0 : $NSObjectBase):

  debug_value %0 : $NSObjectBase, let, name "self", argno 1 // id: %1

  %2 = class_method %0 : $NSObjectBase, #NSObjectBase.Msg_Normal!1 : (NSObjectBase) -> () -> (), $@convention(method) (@guaranteed NSObjectBase) -> () // user: %3

  %3 = apply %2(%0) : $@convention(method) (@guaranteed NSObjectBase) -> ()

  %4 = tuple ()                                   // user: %5

  return %4 : $()                                 // id: %5

} // end sil function 'NSObjectBase.NSObjectBase.callTest() -> ()'

 

// NSObjectBase.callAgain()

sil hidden @NSObjectBase.NSObjectBase.callAgain() -> () : $@convention(method) (@guaranteed NSObjectBase) -> () {

// %0                                             // users: %3, %2, %1

bb0(%0 : $NSObjectBase):

  debug_value %0 : $NSObjectBase, let, name "self", argno 1 // id: %1

  %2 = class_method %0 : $NSObjectBase, #NSObjectBase.Msg_Third!1 : (NSObjectBase) -> () -> (), $@convention(method) (@guaranteed NSObjectBase) -> () // user: %3

  %3 = apply %2(%0) : $@convention(method) (@guaranteed NSObjectBase) -> ()

  %4 = tuple ()                                   // user: %5

  return %4 : $()                                 // id: %5

} // end sil function 'NSObjectBase.NSObjectBase.callAgain() -> ()'

 

 

sil_vtable NSObjectBase {

  #NSObjectBase.Msg_Normal!1: (NSObjectBase) -> () -> () : @NSObjectBase.NSObjectBase.Msg_Normal() -> () // NSObjectBase.Msg_Normal()

  #NSObjectBase.Msg_Second!1: (NSObjectBase) -> () -> () : @NSObjectBase.NSObjectBase.Msg_Second() -> () // NSObjectBase.Msg_Second()

  #NSObjectBase.Msg_Third!1: (NSObjectBase) -> () -> () : @NSObjectBase.NSObjectBase.Msg_Third() -> ()// NSObjectBase.Msg_Third()

  #NSObjectBase.Msg_Objc!1: (NSObjectBase) -> () -> () : @NSObjectBase.NSObjectBase.Msg_Objc() -> () // NSObjectBase.Msg_Objc()

  #NSObjectBase.callTest!1: (NSObjectBase) -> () -> () : @NSObjectBase.NSObjectBase.callTest() -> () // NSObjectBase.callTest()

  #NSObjectBase.callAgain!1: (NSObjectBase) -> () -> () : @NSObjectBase.NSObjectBase.callAgain() -> ()// NSObjectBase.callAgain()

}

 

sil_vtable DerivedOcClass {

  #NSObjectBase.Msg_Normal!1: (NSObjectBase) -> () -> () : @NSObjectBase.NSObjectBase.Msg_Normal() -> () [inherited] // NSObjectBase.Msg_Normal()

  #NSObjectBase.Msg_Second!1: (NSObjectBase) -> () -> () : @NSObjectBase.NSObjectBase.Msg_Second() -> () [inherited] // NSObjectBase.Msg_Second()

  #NSObjectBase.Msg_Third!1: (NSObjectBase) -> () -> () : @NSObjectBase.NSObjectBase.Msg_Third() -> () [inherited] // NSObjectBase.Msg_Third()

  #NSObjectBase.Msg_Objc!1: (NSObjectBase) -> () -> () : @NSObjectBase.NSObjectBase.Msg_Objc() -> () [inherited] // NSObjectBase.Msg_Objc()

  #NSObjectBase.callTest!1: (NSObjectBase) -> () -> () : @NSObjectBase.NSObjectBase.callTest() -> () [inherited] // NSObjectBase.callTest()

  #NSObjectBase.callAgain!1: (NSObjectBase) -> () -> () : @NSObjectBase.NSObjectBase.callAgain() -> () [inherited] // NSObjectBase.callAgain()

apply担任函数绑定和派发的职责

那么阅读就显得简单多了, 可以看到最终对应到 testFunc函数调用的指令有两条.

%4 = class_method %2 : $MyClass, #MyClass.testFunc!1 : (MyClass) -> () -> (), $@convention(method) (@guaranteed MyClass) -> () // user: %5 %5 = apply %4(%2) : $@convention(method) (@guaranteed MyClass) -> () 
  1. class_method: 该指令通过类的函数表来查找函数, 基于类的实际类型.
  2. apply: 传递参数并执行函数.


作者:MaizeJS
链接:https://www.jianshu.com/p/cfe7da01880d
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
o
粉丝 0
博文 500
码字总数 0
作品 0
私信 提问
加载中
请先登录后再评论。
swift class的动态派发

一、测试代码 class BaseCallClass{ func NormalCall(){} @objc func OcCall(){} @objc dynamic func OcDynamicCall(){} } class DerivedCallClass:BaseCallClass{ override func NormalCall......

osc_3fzeg1rk
2019/03/20
4
0
深入理解Swift 派发机制

正文 一张表总结引用类型, 修饰符和它们对于 Swift 函数派发方式的影响. 函数派发就是程序判断使用哪种途径去调用一个函数的机制. 每次函数被调用时都会被触发, 但你又不会太留意的一个东西....

topws1
2019/08/10
0
0
C++、Java、Objective-C、Swift 二进制兼容测试

鉴于目前动态库在iOS App中使用越来越广泛,二进制的兼容问题可能会成为一个令人头疼的问题。本文主要对比一下C++、Java、Objecive-C和Swift的二进制兼容问题。 iOS端动态库使用情况 iOS 8开...

osc_yuku1blu
2019/01/16
2
0
swift 该死的派发机制--待完成

swift 该死的派发机制 final static oc类型 多态类型 静态类型 动态函数 静态函数 nsobject: 1、缺省不再使用oc的动态派发机制; 2、可以使用nsobject暴露出来的接口函数; 3、其它行为与s...

osc_pyq23enu
2019/03/22
10
0
Swift库二进制接口(ABI)兼容性研究

前言 阿里云APP组件化过程中,我们拆分出了若干基础组件库和业务代码库,由于代码是采用Swift编写的,所以这些库都是动态库形式。在上一个正式版本,组件化达到了完全形态,主工程只剩下一个...

osc_ft59t5i9
2018/06/15
2
0

没有更多内容

加载失败,请刷新页面

加载更多

浅谈对python pandas中 inplace 参数的理解

这篇文章主要介绍了对python pandas中 inplace 参数的理解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧 pandas 中 inplace 参数在很多函数中都会有,它的作用是:是否...

Linux就该这么学
16分钟前
9
0
C++ 从基本数据类型说起

前言 int 在32位和64位操作系统,都是四个字节长度。为了能编写一个在32位和64位操作系统都能稳定运行的程序,建议采用std::int32_t 或者std::int64_t指定数据类型。*与long随操作系统子长变...

osc_sxdofc9c
16分钟前
9
0
游戏音乐的作用以及起源

游戏音乐是由特殊的音乐、语言符号、美学符号组成,在电子游戏的发展下,游戏音乐越来越成熟,游戏音乐与美术相融合,能够带给玩家视觉与声音的感官冲击,形成游戏音乐所具有的独特的审美效果...

奇亿音乐
16分钟前
6
0
2020,最新Model的设计-APP重构之路

很多的app使用MVC设计模式来将“用户交互”与“数据和逻辑”分开,而model其中一个重要作用就是持久化。下文中设计的Model可能不是一个完美的,扩展性强的model范例,但在我需要重构的app中,...

osc_mfzkzkxi
17分钟前
4
0
面对职业瓶颈,iOS 开发人员应该如何突破?

我们经常看到 iOS 开发人员(各种能力水平都有)的一些问题,咨询有关专业和财务发展方面的建议。 这些问题有一个共同点:前面都会说“我现在遇到了职业困境”,然后会问一些诸如“我是否应该...

osc_gfpedeca
18分钟前
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部