亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Swift > 正文

淺談在Swift中關于函數指針的實現

2020-03-09 17:50:14
字體:
來源:轉載
供稿:網友
這篇文章主要介紹了淺談在Swift中關于函數指針的實現,是作者根據C語言的指針特性在Swifft中做出的一個實驗,需要的朋友可以參考下
 

Swift沒有什么?

蘋果工程師給我建的唯一一堵墻是:在Swift中沒有任何辦法獲得一個函數的指針:

    注意,C函數指針不會導入到Swift中(來自“Using Swift with Cocoa and Objective-C“)

但是我們怎么知道這種情況下鉤子的地址和跳到哪呢?讓我們深入了解一下,并且看看Swift的func在字節碼層面上的是什么。

當你給一個函數傳遞一個泛型參數時,Swift并沒有直接傳遞它的地址,而是一個指向trampoline函數(見下文)并帶有一些函數元數據信息的指針。并且trampoline自己是包裝原始函數的結構的一部分。

這是什么意思?

讓我們用它來舉個例子:
 

復制代碼代碼如下:

func call_function(f : () -> Int) {
    let b = f()
}
 
func someFunction() -> Int {
    return 0
}

 

在Swift里我們只寫 call_function(someFunction).
但是 Swift 編譯器處理代碼后,性能比調用call_function(&someFunction)好很多
 

復制代碼代碼如下:

struct swift_func_wrapper *wrapper =  ... /* configure wrapper for someFunction() */
struct swift_func_type_metadata *type_metadata = ... /* information about function's arguments and return type */
call_function(wrapper->trampoline, type_metadata);

 

一個包裝器的結構如下:  
 

復制代碼代碼如下:

struct swift_func_wrapper {
    uint64_t **trampoline_ptr_ptr; // = &trampoline_ptr
    uint64_t *trampoline_ptr;
    struct swift_func_object *object;
}

 

什么是 swift_func_object類型? 為了創建對象,Swift 實時使用了一個全局的叫metadata[N]的的常量(每一個 function調用都是唯一的,似的你的func 作為一個泛型的參數,所以對于如下的代碼:  
 

復制代碼代碼如下:

func callf(f: () -> ()) {
    f();
}
callf(someFunction);
callf(someFunction);

 

常量metadata和metadata2會被創建).

一個metadata[N]的結構有點兒像這樣this:
 

復制代碼代碼如下:

struct metadata {
    uint64_t *destructor_func;
    uint64_t *unknown0;
    const char type:1; // I'm not sure about this and padding,
    char padding[7];   // maybe it's just a uint64_t too...
    uint64_t *self; 
}

 

最初metadataN只有2個字段集合:destructor_func 和 type。前者是一個函數指針,將用作為使用swift_allocObject() 創建的對象分配內存。后者是對象類型識別器(函數或方法的0x40 或者 '@'),并且是(某種形式)被swift_allocObject() 用來創建一個正確的對象給我們的func:  
 
swift_allocObject(&metadata2->type, 0x20, 0x7);

一旦func 對象被創建,它擁有下面的結構:
 

復制代碼代碼如下:

struct swift_func_object {
    uint64_t *original_type_ptr;
    uint64_t *unknown0;
    uint64_t function_address;
    uint64_t *self;
}

 

第一個字段是一個指針,用來對應metadata[N]->type 的值,第二個字段似乎是 0x4 | 1 << 24(0x100000004) 并且暗示一些可能 (我不知道是什么)。  function_address 是我們實際掛鉤感興趣的地方,并且self 是 (立即) 自己的指針 (如果我們的對象表示一個普通的函數,這個字段是 NULL)。


好,那么這段我從框架開始如何?事實上,我不明白為什么Swift運行時需要它們,但不論如何,這就是它們原生態的樣子:
 

復制代碼代碼如下:

void* someFunction_Trampoline(void *unknown, void *arg, struct swift_func_object *desc)
{
    void* target_function = (void *)desc->function_address;
    uint64_t *self = desc->self;
 
    swift_retain_noresult(desc->self); // yeah, retaining self is cool!
    swift_release(desc);
 
    _swift_Trampoline(unknown, arg, target_function, self);
    return unknown;
}
 
void *_swift_Trampoline(void *unknown, void *arg, void *target_function, void *self)
{
    target_function(arg, self);
    return unknown;
}

 

讓我們創建它

想象一下,在你的Swift代碼中有這些函數:

 

復制代碼代碼如下:

func takesFunc<T>(f : T) {
    ...
}
func someFunction() {
    ...
}

 

而且你想像這樣生成它們:
 

復制代碼代碼如下:

takesFunc(someFunction)

 

這一行代碼會轉換成相當大的C程序:
 

復制代碼代碼如下:

struct swift_func_wrapper *wrapper = malloc(sizeof(*wrapper));
wrapper->trampoline_ptr     = &someFunction_Trampoline;
wrapper->trampoline_ptr_ptr = &(wrapper.trampoline);
wrapper->object = ({
    // let's say the metadata for this function is `metadata2`
    struct swift_func_object *object = swift_allocObject(&metadata2->type, 0x20, 0x7);
    object->function_address = &someFunction;
    object->self = NULL;
    object;
}); 
 
 
// global constant for the type of someFunction's arguments
const void *arg_type = &kSomeFunctionArgumentsTypeDescription;
// global constant for the return type of someFunction
const void *return_type = &kSomeFunctionReturnTypeDescription;
 
struct swift_func_type_metadata *type_metadata = swift_getFunctionTypeMetadata(arg_type, return_type);
 
takesFunc(wrapper->trampoline_ptr, type_metadata);

 

結構體“swift_func_type_metadata”很不透明,因此我也沒太多可以說的。

回到函數指針

既然我們已經知道函數怎樣作為一個泛型類型參數表示,讓我們借助這個打到你的目的:獲取一個真正指向函數的指針!

我們要做的只是需要注意,我們已經擁有一個作為第一個參數傳遞的trampoline_ptr指針域地址,所以object域的偏移量只是0x8。其他的所有都很容易組合:
 

復制代碼代碼如下:

uint64_t _rd_get_func_impl(void *trampoline_ptr)
{
    struct swift_func_object *obj = (struct swift_func_object *)*(uint64_t *)(trampoline_ptr + 0x8);
 
    return obj->function_address;
}

 

看起來是時候寫寫

 

復制代碼代碼如下:

rd_route(
    _rd_get_func_impl(firstFunction),
    _rd_get_func_impl(secondFunction),
    nil
)

 

但我們怎樣從Swift中調用這些C函數呢?

為此,我們將使用Swift非公開的特性:允許我們提供給C函數一個Swift接口的@asmname屬性。用法如下:
 

復制代碼代碼如下:

@asmname("_rd_get_func_impl")
    func rd_get_func_impl<Q>(Q) -> UInt64;  
 
@asmname("rd_route")
    func rd_route(UInt64, UInt64, CMutablePointer<UInt64>) -> CInt;

 

這就是我們在Swift中使用rd_route()需要的一切。

但是它不能處理任何函數!

也就是說,你不能用rd_route()鉤住任何帶有泛型參數的函數(這可能是Swift的bug,也可能不是,我還沒弄清楚)。但是你可以使用extensions輕松的覆蓋它們,直接指定參數的類型:
 

復制代碼代碼如下:

class DemoClass {
    class func template <T : CVarArg>(arg : T, _ num: Int) -> String {
        return "/(arg) and /(num)";
    }
}
 
DemoClass.template("Test", 5) // "Test and 5"
 
extension DemoClass {
    class func template(arg : String, _ num: Int) -> String {
        return "{String}";
    }
    class func template(arg : Int, _ num: Int) -> String {
        return "{Int}";
    }
}
 
-- Your extension's methods for String and Int will be preferred over the original ones */
DemoClass.template("Test", 5) -- "{String}"
DemoClass.template(42, 5) -- "{Int}"
-- But for other types `template(T, Int)` will be used
DemoClass.template(["Array", "Item"], 5) --- "[Array, Item] and 5"

 

SWRoute

為了在Swift里輕松地勾住函數,我創建了一個名為SWRoute的封裝體—它只是一個小類和一個我們之前寫過的C函數:

 

復制代碼代碼如下:
_rd_get_func_impl():
 
class SwiftRoute {
    class func replace<MethodT>(function targetMethod : MethodT, with replacement : MethodT) -> Int
    {
        return Int(rd_route(rd_get_func_impl(targetMethod), rd_get_func_impl(replacement), nil));
    }
}

 

注意,我們無償進行類型檢查因為Swift需要目標方法和替換具有相同的MethoT類型。

而且我們也無法使用一個復制的原始實現,因此我只能把nil作為另一個參數傳給函數rd_route()。如果你對如何把這個指針集成到Swift代碼有自己的看法,麻煩告訴我!

你可以在資源庫中找到大量SWRoute的實例。

這就是所有的了。



注:相關教程知識閱讀請移步到swift教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
精品久久久久久久中文字幕| 精品久久久免费| 2019中文字幕全在线观看| 日韩成人中文字幕在线观看| 136fldh精品导航福利| 欧美日韩成人黄色| 欧美精品精品精品精品免费| 国产亚洲欧美日韩精品| 日韩免费观看av| 日韩在线中文字幕| 亚洲视频精品在线| 日本免费一区二区三区视频观看| 欧美成人精品xxx| 国产91精品不卡视频| 欧美视频国产精品| 国产精品人成电影在线观看| 欧美性猛交xxxx富婆| 精品久久久久久中文字幕| 久久91精品国产91久久跳| 国产成人精品日本亚洲专区61| 欧美在线视频一区| 成人国产精品色哟哟| 亚洲欧美综合v| 日韩欧美成人精品| 欧美精品福利视频| 亚洲视频在线观看视频| 久久精品这里热有精品| 在线不卡国产精品| 亚洲精品国产福利| 久久亚洲精品中文字幕冲田杏梨| 久久久91精品国产一区不卡| 欧美一级视频在线观看| 91在线视频一区| 中文日韩在线观看| 日本人成精品视频在线| 一区二区亚洲精品国产| 日韩精品视频免费专区在线播放| 午夜免费在线观看精品视频| 中文字幕亚洲欧美日韩2019| 日韩美女免费观看| 国产在线高清精品| 国内揄拍国内精品少妇国语| 久久久99免费视频| 国产精品久久久久久久app| 日韩免费在线电影| 精品夜色国产国偷在线| 国产精品高清在线观看| 欧美专区第一页| 国产精品久久久久久久久久久久| 国产一区二区三区毛片| 伊人久久免费视频| 中文在线资源观看视频网站免费不卡| 2021久久精品国产99国产精品| 日韩av不卡电影| 欧美成aaa人片在线观看蜜臀| 国产在线精品自拍| 久久久久久成人| 国产噜噜噜噜久久久久久久久| 日本高清不卡的在线| 国产一区二区三区18| 在线丨暗呦小u女国产精品| 久久久久久免费精品| 亚洲精品自拍视频| 91精品国产高清久久久久久久久| 国产剧情日韩欧美| 国产精品视频不卡| 日韩欧美中文字幕在线观看| 久久国产一区二区三区| 精品成人乱色一区二区| 欧美专区在线播放| 成人有码视频在线播放| 97视频免费在线观看| 永久免费精品影视网站| 久久精品国产91精品亚洲| 日韩中文综合网| 国产精品永久免费| 日韩大片在线观看视频| 亚洲欧洲av一区二区| 18性欧美xxxⅹ性满足| 欧美黑人xxx| 日韩精品免费在线| 亚洲欧美国产另类| 欧洲成人性视频| 欧美自拍大量在线观看| 亚洲成avwww人| 国产精品国产三级国产aⅴ9色| 91人成网站www| 国产精品久在线观看| 国产午夜精品视频免费不卡69堂| 亚洲毛片在线免费观看| 国产欧美在线观看| 欧美日韩第一视频| 国产精品 欧美在线| 青青草国产精品一区二区| 亚洲女人天堂色在线7777| 精品美女国产在线| 亚洲激情电影中文字幕| 亚洲精美色品网站| 欧美精品做受xxx性少妇| 国产精品wwww| 中文字幕亚洲综合久久| 欧洲美女7788成人免费视频| 国产精品久久久精品| 亚洲免费视频在线观看| 中文字幕av一区中文字幕天堂| 欧美丝袜美女中出在线| 成人深夜直播免费观看| 亚洲欧美综合另类中字| 国产精品久久久久久久app| 国产精品久久久久福利| 国产做受高潮69| 日韩高清av在线| 日韩在线播放av| 欧美高清视频在线观看| 欧美激情久久久久| 亚洲成色www8888| 精品欧美国产一区二区三区| 欧美成人午夜视频| 国产日韩换脸av一区在线观看| 国产成人精品午夜| 精品亚洲精品福利线在观看| 亚洲欧美日韩精品| 91久久精品日日躁夜夜躁国产| 亚洲精品一区中文字幕乱码| 亚洲在线第一页| 欧美激情性做爰免费视频| 中文字幕精品—区二区| 国产精品劲爆视频| 国产日韩精品一区二区| 日韩精品亚洲精品| 在线观看欧美视频| 91精品国产自产在线老师啪| 91久久国产综合久久91精品网站| 中文字幕精品av| 亚洲一区二区中文| 在线播放国产一区中文字幕剧情欧美| 欧美成人h版在线观看| 国内精品久久久久影院优| 国产精品电影久久久久电影网| 亚洲精品v天堂中文字幕| 欧美色另类天堂2015| 国产精品十八以下禁看| 亚洲第一色中文字幕| 国产精品网红福利| 亚洲美女视频网| 亚洲一区制服诱惑| 97视频色精品| 亚洲精品自在久久| www日韩中文字幕在线看| 欧美极度另类性三渗透| 亚洲精品国产精品国自产在线| 国产97色在线|日韩| 欧美午夜视频一区二区| 69**夜色精品国产69乱| 亚洲精品成人久久电影| 亚洲精品天天看| 成人欧美一区二区三区黑人孕妇| 国产精品极品在线| 亚洲第一中文字幕在线观看| 国产精品成人品| 色琪琪综合男人的天堂aⅴ视频| 久久国产精品首页| 亚洲国内高清视频| 一本久久综合亚洲鲁鲁|