しばらくご無沙汰していました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は、見えないのですが、暗黙のルールとして記述するようです。
以下、結果です。
実は、このCとの相互呼び出しは、Swiftに少し慣れてからテストしました。Optional型、関数型の特徴に興味があり、そちらを先に学習したので、(モダンなのに)Cとここまで近いとは気づいていませんでした。Swiftが最初に発表されたき、Objective-CでCのオープンソースをよくリンクして使っていたので、これがやりづらくなるのでは、という心配もありましたが、ダイレクトに呼び出せる(Objective-Cを経由せずの意味)のことでその懸念はなくなりました。
この言語、かなりパワフルです。
Tags: C, Objective-C, Swift