美文网首页
Swift4.1 swift 和 C 的交互

Swift4.1 swift 和 C 的交互

作者: Codepgq | 来源:发表于2018-04-29 16:22 被阅读72次
    C语言基本类型对应表

    其中有三个是特殊的

    • wchar_t - CWideChar
    • char16_t - CChar16
    • char32_t - CChar32
      其他的都是首字母加上 C 然后采用驼峰式命名方法进行命名

    一、基本类型在Swift中如何引用

    • 1、创建C语言类型
    let cInt: CInt = 2
    let cChar: CChar = 49
    
    • 2、引用C语言类型
    .h
    const int global_ten;
    
    
    
    .m
    const int global_ten = 10;
    

    在Swift中使用

    let _ = global_ten
    
    • 3、NS_STRING_ENUMNS_EXTENSIBLE_STRING_ENUM

    NS_STRING_ENUM 通常表示值固定
    NS_EXTENSIBLE_STRING_ENUM 表示可扩展

    .h
    // NS_STRING_ENUM 通常表示值固定
    typedef NSString * PQButtonColor NS_STRING_ENUM;
    
    PQButtonColor const PQButtonColorRed;
    PQButtonColor const PQButtonColorGreen;
    PQButtonColor const PQButtonColorBlue;
    
    // NS_EXTENSIBLE_STRING_ENUM 表示可扩展
    typedef int Shape NS_EXTENSIBLE_STRING_ENUM;
    
    Shape const ShapeCircle;
    Shape const ShapeTriangle;
    Shape const ShapeSquare;
    
    
    
    .m
    
    PQButtonColor const PQButtonColorRed = @"Red";
    PQButtonColor const PQButtonColorGreen = @"Green";
    PQButtonColor const PQButtonColorBlue = @"Blue";
    
    
    
    Shape const ShapeCircle = 1;
    Shape const ShapeTriangle = 2;
    Shape const ShapeSquare = 3; 
    



    使用NS_STRING_ENUM修饰的在swift中生成一个类型与下面的struct
    会把前缀忽略掉

    struct PQButtonColor: RawRepresentable {
        typealias RawValue = String
        
        init(rawValue: Self.RawValue)
        var rawValue: RawValue { get }
        
        static var red: PQButtonColor { get }
        static var green: PQButtonColor { get }
        static var blue: PQButtonColor { get }
    }
    

    swift

    
    extension PQButtonColor{
        static var pink: PQButtonColor {
            return PQButtonColor(rawValue: "Pink")
        }
    }
    
    let bColor: PQButtonColor = .red
    let bColorString = bColor.rawValue // red
    
    
    extension Shape {
        static  var ellise: Shape{
            return Shape(4)
        }
    }
    
    let ellist: Shape = .ellise
    

    两种都可以进行扩展。

    二、简单方法在Swift中如何引用


    • 1、固定参数的方法

    定义

    int add(int a, int b);
    
    int add(int a, int b){
        return a + b;
    }
    

    使用

    //方法
    let sumNum = add(30, 30)
    
    let num1 = 20
    // 这里必要要转化为CInt类型
    let sumNum1 = add(Int32(num1), 2)
    
    • 2、不固定参数的方法
    int vsum(int count, va_list numbers);
    int sum(int count, ...);
    
    
    int vsum(int count, va_list numbers){
        int i = 0, sum = 0;
        while (i < count) {
            sum += va_arg(numbers, int);
            ++i;
        }
        return sum;
    }
    int sum(int count, ...){
        int sum = 0;
        va_list ap;
        va_start(ap, count);
        sum = vsum(count, ap);
        return sum;
    }
    



    使用

    在swift中只能使用vsum这个函数,并不可以使用sum这个函数,因为其不支持...

    没有sum这个方法
    // 使用方法1  需要注意的是 count和数组的元素个数要保持一致
    let _ = vsum(7, getVaList([1,2,3,4,56,7,8]))
    
    // 使用方法2
    let _ = withVaList([1,2,3]){
        vsum(3, $0)
    }
    

    三、简单Struct和union在Swift中如何引用


    • 1、struct

    定义

    typedef struct Location{
        int x,y;
    };
    
    上面代码会在Swift中生成一个struct
    
    struct Location {
        var x: CInt
        var y: CInt
    }
    

    使用

    var loc = Location(x: 0, y: 0);
    
    • 2、为struct添加方法
    Location moveX(Location loc, int delta);
    Location moveY(Location loc, int delta);
    
    .m
    Location moveX(Location loc,int delta){
        loc.x += delta;
        return loc;
    }
    
    Location moveY(Location loc,int delta){
        loc.y += delta;
        return loc;
    }
    

    使用

    loc = moveY(loc, 5)
    

    但是在Swift中是不提倡用这种方式去改变的,应该是用loc.moveX()这样子的方式去调用
    如果想达到这种效果,就要是使用CF_SWIFT_NAME
    moveX为例

    // 使用CF_SWIFT_NAME修饰这个方法,把name变成签名 
    Location moveX(Location loc, int delta) CF_SWIFT_NAME(Location.moveX(self:delta:));
    

    然后就可以在Swift中这样子调用了

    loc = loc.moveX(delta: 5)
    



    通常我还会为struct提供一个工厂方法,在Swift中我们也应该是Location.init去创建,而不是通过一个全局函数去创建

    //工厂方法的创建
    Location createLocation(int) CF_SWIFT_NAME(Location.init(xy:));
    
    .m
    
    Location createLocation(int xy){
        Location loc = { .x = xy, .y = xy };
        return loc;
    }
    

    使用如下:

    //工厂方法
    let _ = Location(xy: 3)
    



    接下来在给struct添加一个getOriginsetOrigin方法

    //getter
    Location getOrigin(void) CF_SWIFT_NAME(getter:Location.origin());
    //setter
    Location setOrigin(Location) CF_SWIFT_NAME(setter:Location.origin(newOrigin:));
    
    Location origin = { .x = 0, .y = 0 };
    Location getOrigin(){
        return origin;
    }
    
    Location setOrigin(Location newOrigin){
        origin = newOrigin;
        return origin;
    }
    

    使用如下:

    // get set
    Location.origin.y = 10
    let _ = Location.origin.x
    
    

    union

    由于Swift并不支持union,所以会在转化的时候变成一个struct

    比如定义一个如下的 union

    typedef union {
        char character;
        int code;
    } ASCII;
    

    在Swift中会转化成为

    /*
    struct ASCII{
        var character: Int8
        var code: CInt
        
        init(character: Int8)
        init(code: CInt)
    }
     */
    

    使用如下:

    let c = ASCII(character: 77)
    

    然后我们看一个稍微复杂一点点的

    // struct and union
    typedef struct {
        union {
            char model;
            int series;
        };
        
        struct {
            double pricing;
            bool isAvailable;
        }info;
        
    } Car;
    

    使用如下:

    let car = Car.init(.init(series: 50), info: .init(pricing: 100, isAvailable: true))
    print(car.series)
    

    在匿名的union中,可以直接调用里面的变量,就像这个对象不存在一样。

    三、enum在Swift中如何引用


    1、申明一个enum

    typedef enum {
        BMW,AUDI,BENZ
    }CarType;
    

    使用

    let _ = BMW
    let _ = AUDI
    let _ = AUDI
    

    这个和我们想象的有差别,不应该是CarType.BMW这样子的形式吗?之所以不是是因为会转化为如下代码

    /*
    struct CarType: RawRepresentable, Equatable {}
    var BMW: CarType { get }
    var AUDI: CarType { get }
    var BENZ: CarType { get }
     */
    

    如果像变成Swift中的样子,要使用NS_ENUM(...)
    里面有两个参数:

    • 第一个参数是类型
    • 第二个是enum名称

    定义和使用

    typedef NS_ENUM(int,PQCarType) {
        PQBMW,PQAUDI,PQBENZ
    };
    
    let bmw: PQCarType = .PQBMW
    

    Demo 地址

    相关文章

      网友评论

          本文标题:Swift4.1 swift 和 C 的交互

          本文链接:https://www.haomeiwen.com/subject/nmeolftx.html