最近不少人詢問筆者如何 porting 既有的 C++ 程式碼到 iPhone/iPad 上,其實大部分的人只是不知如何開始(尤其是原本就不熟悉 Mac 系統的人),而並非真的不會 cross-platform;因此在這裡簡略說明一些小技巧與注意事項,讓往後的開發者能有一個依循的方向。
Objective-C 2.0
Objective-C 可以視為 C 的超集合,而從 Objective-C 2.0 開始支援 C++ 的編譯,通常 Objective-C 2.0 也稱做 Objective-C++, 那我們要如何同時編譯 C++ 原始碼與 Objective-C 原始碼呢,記住兩個準則
- 僅有副檔名為 .mm 的 source file 才支援 C++ 與 Objective-C 原始碼的編譯(同時含有 C++ 與 Objective-C 原始碼在同一個 source file 中)
- Objective-C 的繼承類別與 C++ 的繼承類別各自獨立,即不能交叉繼承
.mm 的 source file 才可以編譯含有 C++ 的原始碼,可以看做為 .cpp 的 source file 才支援 C++ 的編譯,因為預設新增檔案都是 .m 的 source file,不小心或者是初入 Mac 開發不久的 programmer 往往就會在這裡卡關。所以當你要取用 C++ class 請先確保附檔名是否正確,才不會出現一堆莫名奇妙的 compile error。
Objective-C 2.0 代表的是"支援 C++ 的編譯",並非"在 Objective-C 上支援 C++ 語法"或者"在 C++ 上支援 Objective-C 語法",這是很重要的一點,就像小丑魚與海葵共生一樣,互取所需,但是不能一起生小孩。最明顯的例子就是 Objctive-C 的 class 不能繼承 C++ 的 class (反之亦然),也不能在 Objective-C 的 interface 裡用 C++ 的定義函式寫法。
@interface ObjC : NSObject {
void cppMethod();// compile error
};
另外值得一提的事項就是,Objective-C 是一個指標的世界,所以想在 Objective-C class 中取用 C++ class 做為資料成員,請宣告成指標。其它相關注意事項請參考官方文件。
Xcode
通常在 Mac 撰寫跨平台程式碼時,比較好的作法是完整切割 C++ class 與 Objective-C class,將對方視為一個模組的方式取用,但是經驗告訴我們,當既有的程式碼成長到一定程度到難以切割時,就讓它們全部變成 .mm 吧(笑~)。筆者當然不是叫大家做更改副檔名這種傻事,只需做一個小小更動,告訴 Xcode 這些 C++ source file 為 Objective-C++ 類型的檔案即可。
點選所有的 .cpp 檔 -> cmd + I (或右鍵 Get Info),在 General 頁籤可以看到 File Type 的選項,將它從 sourcecode.cpp.cpp 改為 sourcecode.cpp.objcpp。
小丑魚與海葵共生一樣,互取所需…比喻的妙 🙂