swift2でC言語の関数ポインタが利用できるようになった。 例えば、以下のように書けるようになった。
cfile.h
typedef int (*OPERATION)(int, int); int execute(OPERATION operation, int a, int b);
cfile.c
#include "cfile.h" int execute(OPERATION operation, int a, int b) { return (*operation)(a,b); }
sample001-Bridging-Header.h
#include "cfile.h"
main.swift
import Foundation let result:Int32 = execute( { (a:Int32, b:Int32) -> Int32 in return a + b } , Int32(4), Int32(6) ) print("\(result)") // 10
このソースはswift1.2では以下のようなエラーになる。
Cannot invoke 'execute' with an argument list of type '((Int32, Int32) -> Int32, Int32, Int32)'
main.swiftの内容はこのようにも書ける
import Foundation let add: @convention(c) (Int32, Int32) -> Int32 = { (a, b) -> Int32 in return a + b } let result:Int32 = execute(add, Int32(4), Int32(6)) print("\(result)") // 10
@convention(c)がswift2で新たに追加されたシンタックスである。
C言語の関数ポインタなんて使わないんじゃないの?という人もいるだろうが、CoreAudio、CoreMIDI、AudioUnitなどでは必ず使うといってもよい。 もっともよく使うのがこれなどである。
typealias AURenderCallback = CFunctionPointer<((UnsafeMutablePointer<Void>, UnsafeMutablePointer<AudioUnitRenderActionFlags>, UnsafePointer<AudioTimeStamp>, UInt32, UInt32, UnsafeMutablePointer<AudioBufferList>) -> OSStatus)>
swift2のサンプルはこちら
GitHub - pebble8888/audiounitswift: audio unit sample in swift
AVAudioEngineクラスがこれから機能強化されれば、CoreAudioの出番は少なくなりそうではあるが、 関数ポインタを使うフレームワークを使うためだけにObj-Cのソースを書かずに済むのはよい。