zoukankan      html  css  js  c++  java
  • swift class的动态派发

    一、测试代码

    class BaseCallClass{

        func NormalCall(){}

        @objc func OcCall(){}

        @objc dynamic func OcDynamicCall(){}

    }

    class DerivedCallClass:BaseCallClass{

        override func NormalCall(){}

        @objc override func OcCall(){}

        @objc dynamic override func OcDynamicCall(){}

    }

    func FuncTest(object:BaseCallClass)

    {

        object.NormalCall()

        object.OcCall()

        object.OcDynamicCall()

    }

    func DoneTest(){

        FuncTest(object: BaseCallClass())

        FuncTest(object: DerivedCallClass())

    }

    二、命令行

    swiftc -emit-sil DispatchCall.swift | xcrun swift-demangle > DispatchCall.silgen

    cat DispatchCall.silgen

    三、虚函数表

    虚函数表中,函数的名称都以:基类+函数名称的形式定义;

    同时映射到具体的函数;

    sil_vtable BaseCallClass {

      #BaseCallClass.NormalCall!1: (BaseCallClass) -> () -> () : @DispatchCall.BaseCallClass.NormalCall() -> () // BaseCallClass.NormalCall()

      #BaseCallClass.OcCall!1: (BaseCallClass) -> () -> () : @DispatchCall.BaseCallClass.OcCall() -> () // BaseCallClass.OcCall()

    }

    sil_vtable DerivedCallClass {

      #BaseCallClass.NormalCall!1: (BaseCallClass) -> () -> () : @DispatchCall.DerivedCallClass.NormalCall() -> () [override] // DerivedCallClass.NormalCall()

      #BaseCallClass.OcCall!1: (BaseCallClass) -> () -> () : @DispatchCall.DerivedCallClass.OcCall() -> () [override] // DerivedCallClass.OcCall()

    }

    四、动态派发

    1、调用代码:

     // FuncTest(object:)

    sil hidden @DispatchCall.FuncTest(object: DispatchCall.BaseCallClass) -> () : $@convention(thin) (@guaranteed BaseCallClass) -> () {

    // %0                                             // users: %7, %6, %5, %4, %3, %2, %1

    bb0(%0 : $BaseCallClass):

      debug_value %0 : $BaseCallClass, let, name "object", argno 1 // id: %1

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

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

      %4 = class_method %0 : $BaseCallClass, #BaseCallClass.OcCall!1 : (BaseCallClass) -> () -> (), $@convention(method) (@guaranteed BaseCallClass) -> () // user: %5

      %5 = apply %4(%0) : $@convention(method) (@guaranteed BaseCallClass) -> ()

      %6 = objc_method %0 : $BaseCallClass, #BaseCallClass.OcDynamicCall!1.foreign : (BaseCallClass) -> () -> (), $@convention(objc_method) (BaseCallClass) -> () // user: %7

      %7 = apply %6(%0) : $@convention(objc_method) (BaseCallClass) -> ()

      %8 = tuple ()                                   // user: %9

      return %8 : $()                                 // id: %9

    } // end sil function 'DispatchCall.FuncTest(object: DispatchCall.BaseCallClass) -> ()'

    2、虚函数表中的函数派发:

    通过class_method(类的实例变量、函数名称)的形式查找虚函数表到具体的函数;

    然后apply执行;先将函数绑定到类实例,得到方法;然后调用方法执行;

    3、oc的动态派发

    sil提供了对swift方法的统一实现提供了两个实现:oc可见实现和swift具体功能实现;同时将oc可见实现构造进oc的派发列表中;

    派发列表的搜索和oc原生的搜索一致;先搜索子类的实现,没有再搜索父类的实现;

    提供给oc派发列表的函数是一个中间函数,这个函数与具体实现的函数一一对应,并实现了对具体函数的调用;

    先通过objc_method(类的实例变量、函数名称)查找派发列表得到chunk函数;chunk函数与函数的具体实现一一对应;

    然后调用chunk函数;

    chunk函数内部调用函数的具体实现;

    // DerivedCallClass.OcDynamicCall()

    sil hidden @DispatchCall.DerivedCallClass.OcDynamicCall() -> () : $@convention(method) (@guaranteed DerivedCallClass) -> () {

    // %0                                             // user: %1

    bb0(%0 : $DerivedCallClass):

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

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

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

    } // end sil function 'DispatchCall.DerivedCallClass.OcDynamicCall() -> ()'

    // @objc DerivedCallClass.OcDynamicCall()

    sil hidden [thunk] @@objc DispatchCall.DerivedCallClass.OcDynamicCall() -> () : $@convention(objc_method) (DerivedCallClass) -> () {

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

    bb0(%0 : $DerivedCallClass):

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

      // function_ref DerivedCallClass.OcDynamicCall()

      %2 = function_ref @DispatchCall.DerivedCallClass.OcDynamicCall() -> () : $@convention(method) (@guaranteed DerivedCallClass) -> () // user: %3

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

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

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

    } // end sil function '@objc DispatchCall.DerivedCallClass.OcDynamicCall() -> ()'

    五、第三方解释chunk:

    chunk只是包壳,功能有二:1、oc继承体系中派发列表可见;2、消息转发给具体的实现;

    The magic bit of glue here is a thunk. In the Swift to Objective-C world, this is an additional method callable from Objective-C. It’s a thin wrapper and all it needs to do is call through to the native Swift method.

    https://swiftunboxed.com/interop/objc-dynamic/

  • 相关阅读:
    metal的gpu query
    体积雾 global fog unity 及改进
    hdr rt format对颜色的影响
    unity deferred lighting
    unity linear space时 photoshop blend的正确设置
    unity linear work flow
    一些数据 bandwidth之类
    deferred rendering with msaa
    unity 显示mipmaplevel
    【转】在C#中使用SendMessage
  • 原文地址:https://www.cnblogs.com/feng9exe/p/10565979.html
Copyright © 2011-2022 走看看