読者です 読者をやめる 読者になる 読者になる

Pebble's Diary

プログラマーの作業メモ

swift2でC言語の関数ポインタが利用できるようになった(swift2)

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のソースを書かずに済むのはよい。