2016年5月11日 星期三

0511 C如何呼叫SWIFT

/////////////////////新版作法
在.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 
//參考文件
第三部分 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 到底是什麼東西:
  1. xcrun swift-demangle __TFV5hello4Rectg9subscriptFOS_9DirectionSi 
  2. _TFV5hello4Rectg9subscriptFOS_9DirectionSi ---> hello.Rect.subscript.getter (hello.Direction) -> Swift.Int 
當我們從 C 調用的時候,應該規避這樣的名字。還記得前面的 @asmname 麼?沒錯,它可以用於指定 Swift 函數的符號名,我猜測應該有指定 mangled name 的作用,但是不是特別確定。

這裡隨便指定個例子先。
  1. @asmname("say_hello") func say_hello() -> Double { 
  2.     println("This is say_hello() in swift"
  3.     return 3.14 
然後在 .c 文件中:
  1. #include <ProjectName-Swift.h> 
  2.  
  3. extern double say_hello(); 
  4.  
  5. int some_func() { 
  6.   say_hello(); // or capture its value and process it 
  7.   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.
  1. Project must have a Module Name not including spaces.
  2. Defines Module must be set to Yes in Build Settings, under Packaging.
Finally works. Thanks to everyone for the help :-)

沒有留言:

張貼留言

cocos2dx-lua 建立滑鼠監聽

重要關鍵字  EVENT_MOUSE_SCROLL addEventListenerWithSceneGraphPriority      if IsPc() then --建立滑鼠監聽         local listener = cc.EventListenerMouse...