C中的基本類型和基本函數(shù)在Swift中是如何表示的

自從Swift開源并被移植到更多平臺之后托启,一個日益顯現(xiàn)的問題就是它需要更多地和C進行混編屯耸,調(diào)用OS API也好,使用第三方程序庫也好。
因此多矮,接下來的一個話題就是塔逃,從各種基礎(chǔ)類型struct函數(shù)格粪、指針到OC對C的各種擴展匀借,這些語言元素是如何橋接到Swift的呢吓肋?這個系列里,我們就通過一些實際的場景來了解SwiftC交互的方式紫新。

Demo 地址:InteroperateSwiftWithC

C語言中的基礎(chǔ)類型

首先要介紹的芒率,是C中的基礎(chǔ)類型偶芍,大家可以在這里
找到完整的基本類型對應(yīng)表匪蟀,簡單來說宰僧,就是對C中的類型采取駝峰式命名之后段化,加上前綴字母C穗泵。例如:

CType SwiftType.png

int變成 CInt
unsigned char變成CUnsignedChar夷磕;
unsigned long long變成CUnsignedLongLong坐桩;

其中,只有有三個表示寬字符的類型是特殊的:

wchat_t變成CWideChar膘螟;
char16_t變成CChar16
char32_t變成CChar32净当;

于是,在Swift里潭苞,我們可以直接使用這些類型來定義變量此疹,例如:

   let cInt: CInt = 10
   let cChar: CChar = 49

在Xcode里按住option點擊這些類型就會看到蝗碎,它們都是typealias衍菱。例如,CInt的定義是這樣的:

    typealias CInt = Int32

但是辫呻,即便我們知道了這些C類型對應(yīng)的Swift類型放闺,當(dāng)和C代碼交互的時候怖侦,我們也應(yīng)該總是使用這些類型的typealias版本,而不要直接使用這些別名對應(yīng)的原生類型。

traditional_oc.h

#ifndef traditional_oc_h
#define traditional_oc_h
#import <Foundation/Foundation.h>

//導(dǎo)入基本類型的全局變量
const int global_ten;

//NS_STRING_ENUM修飾的類型艳悔,通常表示某個范圍里猜年,值固定的類型
typedef NSString * TrafficLightColor NS_STRING_ENUM;

TrafficLightColor const TrafficLightColorRed;
TrafficLightColor const TrafficLightColorYellow;
TrafficLightColor const TrafficLightColorGreen;

//如果一個類型的值有可能擴展,我們可以使用`NS_EXTENSIBLE_STRING_ENUM`來修飾它
typedef int Shape NS_EXTENSIBLE_STRING_ENUM;

Shape const ShapeCircle;
Shape const ShapeTriangle;
Shape const ShapeSquare;


int add(int m, int n);
int sum(int count, ...);
int vsum(int count, va_list numbers);

#endif

traditional_oc.m

#import "traditional_oc.h"

const int global_ten = 10;

TrafficLightColor const TrafficLightColorRed = @"Red";

TrafficLightColor const TrafficLightColorYellow = @"Yellow";

TrafficLightColor const TrafficLightColorGreen = @"Green";

Shape const ShapeCircle = 1;
Shape const ShapeTriangle = 2;
Shape const ShapeSquare = 3;


int add(int m, int n) {
    return m + n;
}


int sum(int count, ...) {
    va_list ap;
    int s = 0;
    
    va_start(ap, count);
    vsum(count, ap);
    va_end(ap);
    
    return s;
}

int vsum(int count, va_list numbers) {
    int s = 0;
    int i = 0;
    for (; i < count; ++i) {
        s += va_arg(numbers, int);
    }
    return s;
}

main.swift

import Foundation

let ten = global_ten


/*
 對于用NS_STRING_ENUM修飾的TrafficLightColor,引入到Swift就會變成一個類似這樣的struct:
 
 struct TrafficLightColor: RawRepresentable {
      typealias RawValue = String
 
      init(rawValue: RawValue)
      var rawValue: RawValue { get }
 
      static var red: TrafficLightColor { get }
      static var yellow: TrafficLightColor { get }
      static var green: TrafficLightColor { get }
 }
 這個轉(zhuǎn)換規(guī)則是這樣的:
 根據(jù)NS_STRING_ENUM修飾的類型決定導(dǎo)入到Swift時struct的名字,因此,導(dǎo)入的類型名稱就是TrafficLightColor;
 去掉和類型名稱相同的公共前綴莲组,并把剩余部分首字母小寫后锹杈,變成struct的type property;
 */

let redColor: TrafficLightColor = .red
let redColorRawValue = redColor.rawValue // Red


//這樣邪码,按照之前的邏輯闭专,類型Shape在Swift中會被導(dǎo)入成一個struct影钉,它和TrafficLight唯一不同的地方在于平委,多了一個可以省略參數(shù)的init方法夺谁,使得我們可以在Swift里匾鸥,這樣擴展Shape的值:
extension Shape {
    static var ellipse: Shape {
        return Shape(4)
    }
}

let e: Shape = .ellipse

//當(dāng)然扫腺,這并不是說使用NS_STRING_ENUM導(dǎo)入的類型就不可以擴展,例如,我們也可以在Swift里躁劣,這樣擴展TrafficLightColor:

extension TrafficLightColor {
    static var blue: TrafficLightColor {
        return TrafficLightColor(rawValue: "Blue")
    }
}

//從語法上來說账忘,這沒有任何問題。因此溉浙,NS_STRING_ENUM和NS_EXTENSIBLE_STRING_ENUM并不是什么語言層面上的限制戳稽,而只是語義上的差別。面對這種差別,Swift為NS_EXTENSIBLE_STRING_ENUM提供了更為方便的擴展方法罷了颂郎。

基本函數(shù)是如何做橋接的

在Swift里乓序,add會變成這樣:

func add(_ m: Int32, _ n: Int32) -> Int32 {
   return m + n
}

其中有兩點需要注意:

  • C中橋街過來的函數(shù)默認都是省略external name的;
  • C中的int會自動轉(zhuǎn)換成Int32房维,因此默認是不能傳遞Swift Int類型的抬纸,只能使用CInt類型;
let sum = add(32, 23)
  • 它們都是很簡單的C代碼膜蛔,如果你還不熟悉C的可變參數(shù)函數(shù)墅茉,可以先在這里簡單了解下呜呐,我們就不重復(fù)了。這兩個函數(shù)會如何橋接到Swift呢?遺憾的是洋魂,Swift只能接受vsum,而不能接受sum庄岖。也就是說顿锰,無論如何都無法在Swift中直接調(diào)用sum函數(shù)启搂。而vsum橋接到Swift之后,是這樣的:
func vsum(count: Int32, numbers: CVaListPointer) -> Int32
  • 因此,在Swift里疑苫,我們不能像vsum(6, 1, 2, 3, 4, 5, 6)這樣調(diào)用vsum撼短,那么這個CVaListPointer是什么呢挺勿?簡單來說不瓶,它就是C中va_list橋接到Swift后對應(yīng)的類型蚊丐。為了得到這個對象,我們有兩種方法孽椰。

  • 第一種黍匾,是調(diào)用getVaList方法膀捷,并把要傳遞的可變參數(shù)作為一個數(shù)組傳遞給它:

let vaListPointer = getVaList([1, 2, 3, 4, 5, 6])
let sum1 = vsum(6, vaListPointer)
  • 這樣全庸,我們就可以把vaListPointer作為vsum的第二個參數(shù)了壶笼。

  • 第二種,是調(diào)用withVaList方法,它的第一個參數(shù)是一個數(shù)組责语,我們像調(diào)用getVaList一樣把所有可變參數(shù)傳遞給它坤候;第二個參數(shù)是一個closure胁赢,withVaList會根據(jù)第一參數(shù)中的所有成員,生成一個對應(yīng)的CVaListPointer對象徒河,并傳遞給這個closure顽照。因此棒厘,我們只要在closure里調(diào)用vsum就好了:

let sum2 = withVaList([1, 2, 3, 4, 5, 6]) {
    vaListPointer in
    vsum(6, vaListPointer)
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市淆院,隨后出現(xiàn)的幾起案子支救,更是在濱河造成了極大的恐慌拷淘,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件恃轩,死亡現(xiàn)場離奇詭異,居然都是意外死亡蒸殿,警方通過查閱死者的電腦和手機宏所,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人盖腕,你說我怎么就攤上這事溃列√” “怎么了?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長沪么。 經(jīng)常有香客問我禽车,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任栓撞,我火速辦了婚禮瓤湘,結(jié)果婚禮上岭粤,老公的妹妹穿的比我還像新娘。我一直安慰自己巾兆,他們只是感情好角塑,可當(dāng)我...
    茶點故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布圃伶。 她就那樣靜靜地躺著窒朋,像睡著了一般侥猩。 火紅的嫁衣襯著肌膚如雪抵赢。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天,我揣著相機與錄音鹏往,去河邊找鬼掸犬。 笑死,一個胖子當(dāng)著我的面吹牛奠货,可吹牛的內(nèi)容都是我干的座掘。 我是一名探鬼主播,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼睛廊,長吁一口氣:“原來是場噩夢啊……” “哼超全!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起光酣,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤财异,失蹤者是張志新(化名)和其女友劉穎宝当,沒想到半個月后胆萧,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體跌穗,經(jīng)...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡锈拨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年羹唠,在試婚紗的時候發(fā)現(xiàn)自己被綠了奕枢。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片佩微。...
    茶點故事閱讀 38,569評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖哺眯,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤一疯,帶...
    沈念sama閱讀 34,254評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站掌猛,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏眉睹。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,834評論 3 312
  • 文/蒙蒙 一兔院、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧坊萝,春花似錦、人聲如沸十偶。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽毡熏。三九已至痢法,卻和暖如春财搁,著一層夾襖步出監(jiān)牢的瞬間妇拯,已是汗流浹背仗嗦。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留德撬,地道東北人。 一個月前我還...
    沈念sama閱讀 46,260評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親为鳄。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,446評論 2 348

推薦閱讀更多精彩內(nèi)容