Objective-C:swift、objective-c、C++、C混合編程

1 Objective-C調用C++

在Object-C程序有兩種文件.m和.mm文件。 css

  • .m文件是Object-C文件,是徹底兼容C語言,因此能夠在.m文件中直接使用C語言的語法。
  • .mm文件是Object-C++文件,是徹底兼容C++和C語言,因此能夠在.mm文件中直接使用C++和C語言的語法。

因此當須要在Object-C中調用C++時,能夠將.m文件直接重命名爲.mm文件,這樣就可使用C++的語法和內容了。 html

如在main.mm文件: ios

1  #import <Foundation/Foundation.h> 
2  #import <iostream>          // 這裏不是用include C++的頭文件,而是使用import 
3  int main( int argc,  const  char * argv[]) { 
4   @autoreleasepool { 
5      std::cout<< " hello CPP "<<std::endl;  // 徹底是C++的語法 
6  
7   return  0
8 } 

 

2 Swift調用Objective-C

      在Swift文件中要使用Object-C的內容,須要建立一個橋接頭文件,經過橋接頭文件實現Object-C語法到swift語法的轉換,從而以swift的語法,在swift文件中調用Object-C的函數或類等內容。橋接頭文件的命名規則是:<工程名>-swift.h。 編程

若須要在Swift中調用Object-C能夠按以下步驟操做: swift

  1. 新建Object-C格式的Cocoa Class文件,並在建立的過程當中經過Xcode幫忙選擇橋接頭文件;
  2. 在橋接頭文件中,import所須要使用Object-C的頭文件;
  3. 在swift文件中,按Swift語法調用Object-C的內容。

如在swift環境中須要建立Object-C類的對象: 網絡

  • 在Object-C類文件: testObjectC.h 聲明爲:
@interface testObjectC : NSObject 
-(NSString*)sayHello:(NSString*)greeting withName: (NSString*)name; 
@end 

  • 在橋接頭文件的內容爲:
#import  " testObjectC.h "      // 以Object-C的語法import相應的頭文件,目前只需import一個文件 
 
  • 在swift文件的內容爲 :
override func viewDidLoad() { 
super.viewDidLoad() 
//  Do any additional setup after loading the view, typically from a nib. 
var obj : testObjectC = testObjectC();  // 仍按swift語法調用Object—C的構造函數 
var hello = obj.sayHello( " Good morning ", withName: " Tony "
}

 

3 Swift調用C

 在swift文件中調用C語言,與在swift文件中使用Object-C相似,一樣只需在橋接頭文件import相應的頭文件便可ide

3.1 簡單實例

 以下是在Swift環境中調用C語言的函數: 函數

  • 在C語言testC.h文件中的聲明:
#include <stdio.h> 
void printC( int a);  // 在C語言頭文件的聲明,在testC.c文件中還有實現。 

 

  • 在橋接頭文件的內容
#import  " testC.h "  // 仍是以Object-C語法import所須要的C語言頭文件 

 

  • 在swift環境中調用
printC( 2);         // 直接以C語言的語法調用 

 

3.2 類型轉換

       因爲swift和C兩種語言的數據類型定義不徹底相同,特別是在C語言中有指針的類型,而在swift中切沒有,爲了可以在swift環境中調用C語言的API函數,因此Apple在swift環境中定義了一些數據類型,從而可以以C語言的類型一一對應。 url

3.2.1 基本類型

       如表 1所示是Swift環境中C語言調用API函數的數據類型映射表,即若要調用C語言的API,則須要定義表中左邊的類型。 spa

表 1

Swift Type

C Type

CBool

bool

Cchar

char, signed char

CUnsignedChar

unsigned char

Cshort

short

CUnsignedShort

unsigned short

CInt

int

CUnsignedInt

unsigned int

CLong

long

CUnsignedLong

unsigned long

CLongLong

long long

CUnsignedLongLong

unsigned long long

CWideChar

wchar_t

CChar16

char16_t

CChar32

char32_t

CFloat

float

CDouble

double

3.2.2 指針類型

       因爲在swift中沒有指針類型,而C語言中存在指針。因此爲了調用帶有指針類型的C語言API,定義了表 2中swift指針類型。其中表 2中的Type是表 1中左邊swift的基本類型,而且其能夠用於返回值、變量和參數之間的轉換。

表 2

Swift Syntax

C Syntax

UnsafePointer<Type>

const Type *

UnsafeMutablePointer<Type>

Type *

nil

NULL

COpaquePointer

T* (T表示非基本類型)

 

      在C語言中的指針須要手動進行申請空間和釋放空間,一樣在swift語言中也須要手動進行操做;同時在C語言中還可以使用"*"取得指針所在定址,而在Swift中若須要進行賦值和取值,則須要取用相應的方法。

表 3

Swift Syntax

C Syntax

description

static func alloc(num: Int) -> UnsafeMutablePointer<Memory>

Void *malloc(int )

申請定址空間

func dealloc(num: Int)

Void Free(void* )

釋放地址空間

func initialize(newvalue: Memory)

*p = value

給指針所指的地址進行賦值

var memory: Memory { get nonmutating set }

Value = *p

取得地址上的值

&v

&v

取得變量的地址

 

     好比在定義的C語言的函數對指針的值進行修改,經過在swift環境中取得指針的值:

  • C語言函數:
void testPoint( int* a) 

   printf( " %d\n ",*a); 
   *a =  44
}

 

  • swift環境調用
     1  override func viewDidLoad() 
     2 {     
     3      var sp:UnsafeMutablePointer<Int32> = UnsafeMutablePointer<Int32>.alloc( 1); 
     4     sp.memory =  33; //  或者是:sp.initialize(33) 
     5     testPoint(sp); 
     6     print(sp.memory); 
     7     sp.dealloc( 1); 
     8 } 
     9 
    10 
    11 輸出:
    12       33
    13      44
     

3.2.3 字符串

       因爲C語言的字符串能夠簡單分爲兩種:const和非const,因此swift與C語言之間的對應關係如所示。

表 4

Swift Syntax

C Syntax

UnsafeMutablePointer<CChar>

Char *

UnsafePointer

Const char*

 

      雖然swift與C語言之間存在字符串的對應關係,但還需考慮UnsafeMutablePointer<CChar>或UnsafePointer<CChar>類型與swift語言的String字符串之間的轉換。

  • StringàUnsafePointer<CChar>

要將swift語言的String字符串轉換爲C語言的UnsafePointer<CChar>或者是UnsafeMutablePointer<CChar>,須要Object-C的NSString做爲轉換中介。

 

圖 1

  • UnsafePointer<CChar>àString

要將C語言的Unsafe Pointer<CChar>轉換爲swift語言的String,就不須要Object-C做爲中介的,直接調用String類型的fromCString()函數就能夠直接轉換爲Unsafe Pointer<CChar>。

 

圖 2

    

  • C語言函數:
    void testString( char *str) 

       printf( " C:%s\n ",str); 
       strcpy(str, " world "); 
  • swift環境調用
     1  override func viewDidLoad() { 
     2       // 聲明swift、Object-C和C三種語言的字符串進 
     3      var ss:String =  " hello "
     4      var os:NSString ; 
     5      var cs:UnsafeMutablePointer<CChar> = UnsafeMutablePointer<CChar>.alloc( 1); 
     6       // 將swift的字符串ss轉換爲object-C的字符串os,而後將object-C的字符串os轉換爲C語言的字符串cs 
     7      os = NSString.init( string:ss) 
     8      cs = UnsafeMutablePointer<CChar>(os.cStringUsingEncoding( 1)) 
     9      testString(cs);  // 調用C語言的函數 
    10       ss = String.fromCString(cs)!;  // 將C語言的字符串cs直接轉換爲將swift的字符串ss 
    11       print( " swift: "+ss); 
    12 }
  • 輸出:
    C:hello 
    swift:world 

4 swift調用C++

 

       目前沒法直接調用,須要一些特別的技巧。若須要能夠經過Object-C對C++進行包裝,而後在swift中調用Object-C,既以swiftàObject-CàC++這樣的順序調用。

5 參考文獻

 

  1. Apple:《Using swift with cocoa and Objective-C 》P174
  2. 書:《swift開發指南》P232;
  3. Apple:《Using Swift with Cocoa and Objective-C (Swift 2.1): Interacting with C APIs》
相關文章
相關標籤/搜索