iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 29
0
Mobile Development

30 天從 Swift 學會 Objective-C系列 第 29

[29] 30 天從 Swift 學會 Objective-C:Swift friendly 的 進階 C 語言部分與 modulemap

在理解完 Objective-C 之後,我們要來面對 C 語言的引用,不得不說 Swift 十分不信任 C 語言,看看那個UnsafePointer 就知道了。


Photo by @filipz on Unsplash

C 語言程式碼匯入到 Swift project

當我們使用 Xcode 在 Swift projcet 建立 C/Objective-C 檔案時,Xcode 會提示我們 Xcode 可以自動建立需要的 bridge header

Importing Objective-C into Swift - Apple Developer Documentation
中有這麼一張圖:

圖片來自 Importing Objective-C into Swift - Apple Developer Documentation

我們可以知道在 C/Objective-C 都是使用 .h 作為 header 的副檔名,透過在 bridge Header 內引用相關的Header, Swift 編譯器可以確認納入編譯來源的檔案。

[進階] 只有 C 語言的 .h 與 .a

在 C 語言的編譯過程中有所謂的 linker 階段,在 clang 可以將單個 .c 檔案編譯為 .o 檔案。

 clang -c CFunctions.c -o CFunctions.o

透過使用 -c 的參數指定 compile 成 obj 檔案,而這個 Obj 檔案可以保留作為節省編譯資源的方式(時間與電量)。

.a 是透過 ar 指令將指定的 obj 檔案建立為靜態函式庫。

關於 靜態函式庫與共享函式庫,參考 Static library - Wikipedia

[我看不懂的部分] 在 Swift 引入靜態函式庫

在使用 C 的靜態函式庫時,我們可以用 Framework, Libaraies, and Embedded Content 來使用,目前我實作了
rderik/Csqlite3 - GitHub 是可以使用的,其中 Sources/module.modulemap 內使用的是來自系統的 header。

範例來自 rderik/Csqlite3 - GitHub

然而我嘗試透過 ar 建立靜態函式庫並應用進來 modulemap 時,header 的 obj 卻遺失導致無法編譯成功。由於截稿壓力無法完成研究。

關於 Swift 不信任 C 語言這件事

在使用 bridge header 引入 C 語言的程式碼後,使用 char* 會遇到 UnsafeMutablePointer<Int8>!

這部分我使用的方式時拖過 adapter 的方式,藉由 Swift package 來處理。

程式碼範例於 ytyubox/lib_mylib - GitHub

關於這部分的詳細解釋,我推薦 Cecilia Humlelu 在 App Builders 2019 的介紹

Use C, C++ and Objective C Libraries in a Swift Project - Cecilia Humlelu - App Builders 2019 On Youtube

簡單測驗

  1. 在 C 語言中,如何判讀一個 char* 的長度 (length)? 這與 Swift 的 String count 有區別,那區別是什麼?
  2. modulemap 是 Swift feature 還是 C 語言的?

上一篇
[28] 30 天從 Swift 學會 Objective-C:Swift friendly 的 API Swift name
下一篇
[30] 30 天從 Swift 學會 Objective-C:30 天內那些我不懂的部分
系列文
30 天從 Swift 學會 Objective-C30

尚未有邦友留言

立即登入留言