iOS中的COCOAPODS+POSIX的坑

1.背景

    现在的移动端开发,越来越追求iOS和Android能够使用一套代码就能二者兼得的模式。这种情况下由于不需要维护两套代码,因此在某种程度下能够降低错误的风险。
    二者融合的模式中,一种方式便是使用w3c标准的web形式,这也是Hybrid的主要概念来源。于是各种Hybrid框架层出不穷,从PhoneGap到现在流行的React-Native都属于此类。
    然而,事实上还有一种方式,便是采取纯c/c++编写程序,iOS和Android共享底层代码来达到相同目的的方法。这里的标准叫做POSIX。我们也正是基于这种考虑,让iOS, Android, PC 都公用一套代码,增加代码的复用,减少问题的发生概率。

2.我们的解决方案

    在iOS端,为了达到复用同一套C/C++代码,并且不对原代码破坏的目的,我们采用的也是CocoaPods的方案。使用CocoaPods将该功能所有的C/C++建立一套Pod库,编译成静态库,来达到共享的目的。

3.问题的产生

    工程师兄弟都知道,需求是在不断进(keng)步(die)的。基于此,底层的共享库也会经常地有所变动。为了达到这次需求的目的,底层的兄弟直接从纯C改用了C++编写,而这也是困扰了我整整两天的问题根源。看到这里,可能会有懂行的产生疑问,C++不是兼容C的吗?
    对,没错,C++是兼容C;但是问题在于C,并不兼容C++。

4.寻源

    Apple的OS底层是XNU(Mach+Darwin), 也是一套遵循了POSIX标准的内核,主要从UNIX中来。不过,它并不是100%兼容GNU/Linux的标准,因此在C/C++的编译上便会产生一系列偏差,虽然这种概率并不大。
    XCode中的libc++就是采用了Apple自己标准的C++协议库。如上所说,这个库会导致一些在Linux下编译ok的库在iOS上无法链接成功(非100%兼容GNU/C++)。
    这种情况下,就需要使用Apple提供的另一个库:libstdc++(libstdc++.6.0.9代表不同版本的libstdc++),这个东西是GNU/C++ 100%兼容的。

5.兼容

    原以为解决以上问题就可以成功连接,却还是出现undefine symbols错误。
    仔细想想,发现原来问题的关键在于.m文件。
    事实上,iOS中除了Object-C 开发,还有一个东西叫做Object-C++。Object-C++文件是以.mm后缀结尾的。当llvm编译器看到.mm文件时,会自动调用Object-C++的标准来编译和连接该文件。
    在之前的版本中,底层的兄弟采用的是.c文件来编写相关的代码;这次换成.cpp文件后,llvm编译这样文件时候编的是c++。而直接调用这些函数的代码又是.m,即Object-C,遵循C标准。最后Linking阶段导致了符号表找不到的问题。
    修改.m文件后缀为.mm,编译,通过,收工。

6.经验

    C/C++并不一样。如果.m文件要调用的是在.cpp文件内的函数,一定改成.mm。
libstdc++、libstdc++.6.0.0、libc++都是不一样的。如果一种库连接不起来,尝试使用另一种,说不定可以带来惊喜。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,245评论 4 61
  • 一条扭曲的蛇贯穿体内 它是来自社会的阴沟和污水 怎样才能摆脱它? 只有自己内心的意志和坚定
    舒严阅读 218评论 0 0
  • 很多年后,当我们坐在窗台,窗外的阳光透过玻璃渗透到那发黄的书页,我们看着黄昏里的群岚,触摸曾经写下纸上的字迹,你会...
    西蜀三三三阅读 217评论 1 1
  • 今天抽牌时在想:今天又是新的一天,会有什么新的启示给我?今天要开家长会,会不会有新的认识? 抽中的是第一个火牌:源...
    美伊g阅读 1,156评论 1 5