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》
相关文章
相关标签/搜索