/////////////////////新版作法
在.swift 中
@_silgen_name ("isConnectedToNetwork") func isConnectedToNetwork()->Bool指定函數名稱 (swift 2.2 以前用 @asmname )
在CPP中 不用引用.H
extern bool isConnectedToNetwork();
return isConnectedToNetwork();
將CPP 改為.mm 就可以OC 與C 相互編譯
////////////////////////////////////////
1.C 引用 #include <ProjectName-Swift.h>
2. ProjectName-Swift.h 產生記得要開啟 Build Settings->Packaging -> Defines Module = YES
3. ProjectName 不能有空格或是非子母字元否則預設會用底線取代,通常預設是TARGETS 名稱
名稱可以看屬性 swift complier->Objective-c Generated
名稱可以看屬性 swift complier->Objective-c Generated
http://stackoverflow.com/questions/24062618/swift-to-objective-c-header-not-created-in-xcode-6 Swift to Objective-C header not created in Xcode 6
//參考文件
第三部分 C 調用 Swift
如果項目裡加入了 C 文件,那麼它可以調用我們的 Swift 函數麼?答案是可以的,而且令人吃驚地透明。這也許是因為 Apple 所宣傳的,Small Runtime 概念吧。極小的語言運行時。
和 Objective-C 混編類似,配置好 Bridging Header 的項目,在 .c .h .m 文件中都可以使用一個叫做 ProjectName-Swift.h 的頭文件,其中包含 Swift 代碼導出的函數等。
參考之前的 Objective-C 和 C 交互我們可以知道,說到底交互就是鏈接過程,只要鏈接的時候能找到符號就可以。
不過不能高興太早,Swift 是帶類、枚舉、協議、多態、泛型等的高級語言,符號處理明顯要比 C 中的複雜的多,現代語言一般靠 name mangle 來解決這個問題。也就是說一個 Swift 函數,在編譯到 .o 的時候,名字就不是原來那麼簡單了。比如 __TFV5hello4Rectg9subscriptFOS_9DirectionSi 這樣的名字。
Xcode 自帶了個工具, 可以查看這些 mangled name 到底是什麼東西:
- xcrun swift-demangle __TFV5hello4Rectg9subscriptFOS_9DirectionSi
- _TFV5hello4Rectg9subscriptFOS_9DirectionSi ---> hello.Rect.subscript.getter (hello.Direction) -> Swift.Int
當我們從 C 調用的時候,應該規避這樣的名字。還記得前面的 @asmname 麼?沒錯,它可以用於指定 Swift 函數的符號名,我猜測應該有指定 mangled name 的作用,但是不是特別確定。
這裡隨便指定個例子先。
- @asmname("say_hello") func say_hello() -> Double {
- println("This is say_hello() in swift")
- return 3.14
- }
然後在 .c 文件中:
- #include <ProjectName-Swift.h>
- extern double say_hello();
- int some_func() {
- say_hello(); // or capture its value and process it
- return 0
- }
對於函數而言 extern 必須手動加上,對於 class 、 protocol ,會在生成的頭文件裡。
按照這個思路,其實很容易實現 Swift 調用 C 中調用了 Swift 函數的函數。這意味著,可以通過簡單的方法封裝支持向 C 傳遞 Swift block 作為回調函數。難度中上,對於有過類似擴展編寫經驗的人來說很簡單
//參考文件設定 如何產生 ProjectName-Swift.h
自翻譯
1.專案名稱不能有空格
2.Build Settings, Packaging 的設定
Defines Module = YES
原文
Now it works.
- Project must have a Module Name not including spaces.
- Defines Module must be set to Yes in Build Settings, under Packaging.
Finally works. Thanks to everyone for the help :-)
沒有留言:
張貼留言