LoginSignup
11
17

More than 5 years have passed since last update.

Swiftの関数やクロージャをC言語の関数ポインタとして処理する

Last updated at Posted at 2016-05-24

概要

前回はCからSwiftの関数を呼び出してみる方法を書いたけど、swift.hというヘッダを別に用意する必要があって面倒だし1@_silgen_name("...")というattributeもなんだか怪しげな匂いがするし、…というわけで、Swiftの関数やクロージャをC言語の関数ポインタとして処理するという方法もあるので書いてみる。

要約

  1. @convention(c)を使う。
  2. 以上(これだけで解った貴方はこの記事を読む必要はありません)

環境

  • OS X = OS X El Capitan + Xcode 7.3 (Swift 2.2)
  • Linux = CentOS 7 + Swift 2.2.1
OS X
$ clang --version
Apple LLVM version 7.3.0 (clang-703.0.29)
Target: x86_64-apple-darwin15.5.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

$ swift --version
Apple Swift version 2.2 (swiftlang-703.0.18.1 clang-703.0.29)
Target: x86_64-apple-macosx10.9
Linux
$ clang --version
clang version 3.8.0 (tags/RELEASE_380/final)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /usr/local/bin

$ swift --version
Swift version 2.2.1 (swift-2.2.1-RELEASE)
Target: x86_64-unknown-linux-gnu

ソースファイル

前々回と同様、ファイルは3つだけ。

$ ls
c.c  c.h  swift.swift
c.h
#include <unistd.h>
void call_me_later(void (*closure)(), unsigned int seconds);
c.c
#include "c.h"
void call_me_later(void (*closure)(), unsigned int seconds) {
  sleep(seconds);
  closure();
}
swift.swift
func swift_function() {
  print("I just woke up! Yes, I'm Function.")
}
let swift_closure:@convention(c) ()->() = {
  print("I just woke up! Uh-oh, I'm Closure.")
}
call_me_later(swift_function, 0)
call_me_later(swift_closure, 2)

※関数であれば@convention(c)すら要らない。

コンパイル手順

C言語ソースからオブジェクトファイルを作成

OS X, Linux共通
$ clang -c c.c -oc.o
$ ls
c.c  c.h  c.o  swift.swift

オブジェクトファイルと一緒にSwiftソースをコンパイル

OS X
$ xcrun --sdk macosx swiftc swift.swift c.o -import-objc-header c.h
ld: warning: object file (c.o) was built for newer OSX version (10.11) than being linked (10.9)
$ ls
c.c     c.h     c.o     main        swift.swift
$ ./main
I just woke up! Yes, I'm Funtion.
I just woke up! Uh-oh, I'm Closure.
Linux
$ swiftc swift.swift c.o -import-objc-header c.h
$ ls
c.c  c.h  c.o  main  swift.swift
$ ./main
I just woke up! Yes, I'm Funtion.
I just woke up! Uh-oh, I'm Closure.

できた。これでおわり。
ね、簡単でしょう2


  1. 小規模なプロジェクトならc.cに関数プロトタイプを書くだけでもいいけど…ね? 

  2. ググればいろいろ応用編がありそうですね。 

11
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
17