前回、Swift, Objective-Cの相互呼び出しのテストをしましたが、CからSwiftの呼び出しについては、Objective-C経由で十分と考えていました。CとSwiftの「近さ」を実感するために、ここをもう少し踏み込んでテストしてみたいと思います。
環境 : Swift 1.2, Xcode 6.3 / Mac OSX 10.10.3
- (void) callSwift2 { MySwiftClass *my = [[MySwiftClass alloc] init]; SEL method = @selector(disp:); [my performSelector: method withObject:@"NS String 2 / Objc"]; } - (void) callSwift3 { MySwiftClass *my = [[MySwiftClass alloc] init]; SEL method = @selector(disp:); IMP func = [my methodForSelector: method]; // C Function ((void(*)(id, SEL, NSString*))func)(my, method, @"NS String 3 / Objc"); }
主に上記二つのメソッド追加しました。
前回からSwiftもバージョンアップしたので、OSもXcodeもアップグレードして、再びビルドしました。
また、プログでは初めて、コードをgithubにアップしました。関連プログでもこれから活用していくつもりです。
https://github.com/systemsblue/CBridge
callSwift3で、Cの関数のようにSwiftのメソッドを呼び出しているところがポイントです。
さらに、Pythonのctypesを使って、Swiftのメソッドをダイナミックライブラリにして無理やり呼び出してみました。
add.swift
public func add(a:Int, b:Int) -> Int { return a + b }
コマンド
xcrun swiftc -emit-library -emit-object add.swift -o add.o
xcrun libtool -dynamic -lswiftCore -lsystem -o add.dylib add.o -L/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx
nm add.dylib
symbol table表示結果
0000000000000f70 T __TF4addf3addFTSiSi_Si
0000000000000f64 t __dyld_func_lookup
U dyld_stub_binder
0000000000000f50 t dyld_stub_binding_helper
メソッド_TF4addf3addFTSiSi_Siをpython(REPL)から呼び出す。
Python 2.7.6 (default, Sep 9 2014, 15:04:36) [GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.39)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> from ctypes import * >>> cdll.LoadLibrary('/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/libswiftCore.dylib') <CDLL '/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/libswiftCore.dylib', handle 7f83b9e010f0 at 10b5874d0> >>> my = cdll.LoadLibrary('./add.dylib') >>> my._TF4addf3addFTSiSi_Si(1,2) 3 >>>
やはりCなのですね。
Pythonのctypesは、Cの構造体にもアクセスでき、dylib(Mac), dll(Window), so(Linux)にアクセスするときによく使われます。(前回やったようにSwiftも構造体にアクセス可という点で似ています)
オブジェクト指向を取り入れたのが、Objective-Cなら、関数型言語の特徴を取り入れたSwiftは、Functional-Cと呼んでもいいくらい、Cに「近い」と感じました。(見た目はかなり違いますが)