1.背景
????現(xiàn)在的移動端開發(fā),越來越追求iOS和Android能夠使用一套代碼就能二者兼得的模式。這種情況下由于不需要維護(hù)兩套代碼,因此在某種程度下能夠降低錯誤的風(fēng)險。
????二者融合的模式中眉踱,一種方式便是使用w3c標(biāo)準(zhǔn)的web形式,這也是Hybrid的主要概念來源霜威。于是各種Hybrid框架層出不窮谈喳,從PhoneGap到現(xiàn)在流行的React-Native都屬于此類。
????然而戈泼,事實上還有一種方式婿禽,便是采取純c/c++編寫程序,iOS和Android共享底層代碼來達(dá)到相同目的的方法矮冬。這里的標(biāo)準(zhǔn)叫做POSIX谈宛。我們也正是基于這種考慮,讓iOS, Android, PC 都公用一套代碼胎署,增加代碼的復(fù)用吆录,減少問題的發(fā)生概率。
2.我們的解決方案
????在iOS端琼牧,為了達(dá)到復(fù)用同一套C/C++代碼恢筝,并且不對原代碼破壞的目的哀卫,我們采用的也是CocoaPods的方案。使用CocoaPods將該功能所有的C/C++建立一套Pod庫撬槽,編譯成靜態(tài)庫此改,來達(dá)到共享的目的。
3.問題的產(chǎn)生
????工程師兄弟都知道侄柔,需求是在不斷進(jìn)(keng)步(die)的共啃。基于此暂题,底層的共享庫也會經(jīng)常地有所變動移剪。為了達(dá)到這次需求的目的,底層的兄弟直接從純C改用了C++編寫薪者,而這也是困擾了我整整兩天的問題根源纵苛。看到這里言津,可能會有懂行的產(chǎn)生疑問攻人,C++不是兼容C的嗎?
????對悬槽,沒錯怀吻,C++是兼容C;但是問題在于C初婆,并不兼容C++烙博。
4.尋源
????Apple的OS底層是XNU(Mach+Darwin), 也是一套遵循了POSIX標(biāo)準(zhǔn)的內(nèi)核,主要從UNIX中來烟逊。不過,它并不是100%兼容GNU/Linux的標(biāo)準(zhǔn)铺根,因此在C/C++的編譯上便會產(chǎn)生一系列偏差宪躯,雖然這種概率并不大。
????XCode中的libc++就是采用了Apple自己標(biāo)準(zhǔn)的C++協(xié)議庫位迂。如上所說访雪,這個庫會導(dǎo)致一些在Linux下編譯ok的庫在iOS上無法鏈接成功(非100%兼容GNU/C++)。
????這種情況下掂林,就需要使用Apple提供的另一個庫:libstdc++(libstdc++.6.0.9代表不同版本的libstdc++)臣缀,這個東西是GNU/C++ 100%兼容的。
5.兼容
????原以為解決以上問題就可以成功連接泻帮,卻還是出現(xiàn)undefine symbols錯誤精置。
????仔細(xì)想想,發(fā)現(xiàn)原來問題的關(guān)鍵在于.m文件锣杂。
????事實上脂倦,iOS中除了Object-C 開發(fā)番宁,還有一個東西叫做Object-C++。Object-C++文件是以.mm后綴結(jié)尾的赖阻。當(dāng)llvm編譯器看到.mm文件時蝶押,會自動調(diào)用Object-C++的標(biāo)準(zhǔn)來編譯和連接該文件。
????在之前的版本中火欧,底層的兄弟采用的是.c文件來編寫相關(guān)的代碼棋电;這次換成.cpp文件后,llvm編譯這樣文件時候編的是c++苇侵。而直接調(diào)用這些函數(shù)的代碼又是.m赶盔,即Object-C,遵循C標(biāo)準(zhǔn)衅檀。最后Linking階段導(dǎo)致了符號表找不到的問題招刨。
????修改.m文件后綴為.mm,編譯哀军,通過沉眶,收工。
6.經(jīng)驗
????C/C++并不一樣杉适。如果.m文件要調(diào)用的是在.cpp文件內(nèi)的函數(shù)谎倔,一定改成.mm。
libstdc++猿推、libstdc++.6.0.0片习、libc++都是不一樣的。如果一種庫連接不起來蹬叭,嘗試使用另一種藕咏,說不定可以帶來驚喜。