SwiftからC

Cの函数は,Swiftから直接呼び出せる。

自前のソース

Xcodeを使う場合

  1. Xcodeのプロジェクトを作成(例: foo)する。
  2. Command Line Toolを選ぶ。
  3. 言語はSwiftを選択。
  4. Cのソースを追加。ヘッダも一緒に作る。
  5. Bridging Headerをconfigureしてもらい,foo-Bridging-Headers.hに必要なソースを#include。
  6. モジュールはXCodeが作ってくれはる。

コマンドライン

オプション-import-objc-headerを使って名前を解決し,Swiftのソースをコンパイルする。推奨しないと断って,stackoverflowの質疑に書いてある。Xcode 6-Beta5からはSwiftコンパイラの名前がswiftcとなった。
$ xcrun swiftc -c main.swift -import-objc-header addtwo.h
$ clang -O2 -c addtwo.c
$ xcrun swift main.o addtwo.o -o addtwo

Makefile

CC = /usr/bin/clang
CFLAGS = -O3
SWIFT = /usr/bin/xcrun swiftc
TARGET = addtwo
OBJS = $(TARGET).o main.o
HDRS = $(TARGET).h

all : $(TARGET)

$(TARGET) : $(OBJS)
 $(SWIFT) $^ -o $@
%.o : %.swift
 $(SWIFT) -c $< -import-objc-header $(HDRS)

clean :
 rm $(TARGET) *.o

addtwo.c

#include "addtwo.h"
double addtwo(double x, double y)
{
 return x + y;
}

Swift

var x = 1.0
var y: Double = 2.0
println(addtwo(x, y))
CのdoubleはSwiftのCDoubleに対応するが,型推論を使っても,Doubleでも正しく動作する。変数は値渡し。

配列

double *はUnSafePointerだが,Swift blogにある通りSwiftのarrayのアドレスを直接渡せる。

csum.c

#include "csum.h"
double csum(const double * x, long n) {
 double y = 0;
 for (int i = 0; i < n; i++) {
 y += x[i];
 }
 return y;
}

Swift

let v = [1.0, 2.0, 3.0]
println(csum(v, v.count))
var w = [4.0, 5.0, 6.0]
println(csum(&w, w.count))
const double*にはletで定義した書き換え不可の配列やvarで定義した配列のアドレスが渡せる。

ライブラリ

外部のライブラリは,ライブラリとヘッダをプロジェクトに追加する。ちなみに共有ライブラリは次のように作る。
$ clang -dynamiclib -Wl,-install_name パス オブジェクトファイル -o ライブラリ名.dylib

Framework

Accelerate.frameworkを使う。
  1. Xcode左のNavigatorでプロジェクトファイルを選択。
  2. Build PhasesのLink Binary With Librariesの+をクリック。Accelerate.frameworkを追加。
  3. import Accelerate
  4. foo-Bridging-HeadersにAccelerate.hを#includeする必要はない。

Swift

import Accelerate
let s1 = [1.0, 1.0, 2.0]
let s2 = [1.0, 1.0, 0.5]
println(cblas_ddot(CInt(s1.count), s1, 1, s2, 1))
Accelerateは,XcodeプロジェクトだけでなくREPLでも同様にimportして使える。

コメント

このブログの人気の投稿

静的サイト生成ツールの導入

uptex

TeXのソースを分割してTeXShopでタイプセット