Swift : without C ?

しばらくご無沙汰していましたiOS開発を再び始めることになりました。
新しい言語のSwiftを使っていろいろと作っていますが、C言語との「距離」が意外と近い、という印象を強くうけます。
「わさび抜きわさビーフ」ではないですが、C抜きの(Cにみえない)C言語みたいな感じでしょうか。
関数型言語のアイディアをふんだんに取り入れた、高機能な言語に仕上がっているのは、もちろんですが、Objective-C, C との相互やりとりは簡単にできるようになっています。
そこで、相互呼び出しのテストをしてみました。

環境 : Xcode 6.2 / Mac OSX 10.9.5

main.swift

import Foundation

class MySwiftClass : NSObject{
    func disp(str:NSString){
        println("Swift : \(str)")
    }
}

var my = MyObjcClass()

var str:NSString = "NS String / Swift";
my.disp(str)
my.callSwift()

var i:CInt = 0
var cstr = UnsafeMutablePointer<CChar>.alloc(10)

getStr(cstr)
println(String.fromCString(cstr)!)

getInt(&i)
println("number : \(i)")

var ii:CInt = 0
var cstr2 = [CChar](count:20, repeatedValue:0)

var cst1 = cStruct(name:&cstr2, number:ii)
getStruct1(&cst1)
println("\(String.fromCString(cst1.name)!) : \(cst1.number)")

var cst2:cStruct = getStruct2()
println("\(String.fromCString(cst2.name)!) : \(cst2.number)")

var cst3:UnsafeMutablePointer<cStruct> = getStruct3()
println("\(String.fromCString(cst3.memory.name)!) : \(cst3.memory.number)")

sub01.h

#import <Foundation/Foundation.h>

@interface MyObjcClass : NSObject
- (void) disp:(NSString*)str;
- (void) callSwift;
@end

sub01.m

#import "CBridge-Swift.h"
#import "sub01.h"

@implementation MyObjcClass
- (void) disp:(NSString*) str {
    NSLog(@"Objc : %@", str);
}
- (void) callSwift {
    MySwiftClass *my = [[MySwiftClass alloc] init];
    [my disp:@"NS String / Objc"];
}
@end

CBridge-Bridging-Header.h

#import "sub01.h"
#import "sub02.h"

sub02.h

#include <stdio.h>
#include <string.h>

void getInt(int *i);
void getStr(char *str);

typedef struct{
    char *name;
    int number;
} cStruct;

void getStruct1(cStruct *st);
cStruct getStruct2();
cStruct* getStruct3();

sub02.c

#include "sub02.h"
#include <stdlib.h>
#include <string.h>

void getInt(int *i){
    *i = 1234;
}
void getStr(char *str){
    strcpy(str, "C String / Clang");
}
void getStruct1(cStruct *st){
    st->name = "name of cStruct1";
    st->number = 1111;
}
cStruct getStruct2(){
    cStruct *st = malloc(sizeof(cStruct));
    st->name = "name of cStruct2";
    st->number = 2222;
    return *st;
}
cStruct* getStruct3(){
    cStruct *st = malloc(sizeof(cStruct));
    st->name = "name of cStruct3";
    st->number = 3333;
    return st;
}

SwiftからCの呼び出しは、UnsafeMutablePointerを使うところとC構造体がそのままSwift側で使えてしまうところが、ポイントです。
構造体は3とおりの呼び出しを試しました。
SwiftとObjective-Cとの相互呼び出しは、簡単にできてしまいます。
CBridge-Bridgeing-Header.hは、コードを追加するときに作成するか聞いてきます。ここにはC,Objective-Cのヘッダを読み込みます。
CBridge-Swift.hは、見えないのですが、暗黙のルールとして記述するようです。
以下、結果です。
CBridge

実は、このCとの相互呼び出しは、Swiftに少し慣れてからテストしました。Optional型、関数型の特徴に興味があり、そちらを先に学習したので、(モダンなのに)Cとここまで近いとは気づいていませんでした。Swiftが最初に発表されたき、Objective-CでCのオープンソースをよくリンクして使っていたので、これがやりづらくなるのでは、という心配もありましたが、ダイレクトに呼び出せる(Objective-Cを経由せずの意味)のことでその懸念はなくなりました。
この言語、かなりパワフルです。

Tags: , ,

Leave a Reply