C++ 未找到架构i386的符号-但适用于iOS设备

C++ 未找到架构i386的符号-但适用于iOS设备,c++,ios,cocoa-touch,ios6,cross-compiling,C++,Ios,Cocoa Touch,Ios6,Cross Compiling,我在这里面临一个奇怪的问题,我正在尝试将集成到我的iOS项目中。项目可以独立编译,但当涉及到通过这行代码进行链接时: kmldom::PointPtr appPoint = kmlconvenience::CreatePointLatLon(appLocation.coordinate.latitude, appLocation.coordinate.longitude); 只有在为模拟器构建链接器时,才会出现链接器错误。当我为iOS设备构建它时,它可以正常工作,但对于模拟器,我得到以下3个链

我在这里面临一个奇怪的问题,我正在尝试将集成到我的iOS项目中。项目可以独立编译,但当涉及到通过这行代码进行链接时:

kmldom::PointPtr appPoint = kmlconvenience::CreatePointLatLon(appLocation.coordinate.latitude, appLocation.coordinate.longitude);
只有在为模拟器构建链接器时,才会出现链接器错误。当我为iOS设备构建它时,它可以正常工作,但对于模拟器,我得到以下3个链接器错误:

(null): "kmldom::GxTimeSpan::GxTimeSpan()", referenced from:

(null): Kmldom::KmlFactory::CreateGxTimeSpan() const in libLibKML.a(kml_factory.o)

(null): "kmldom::GxTimeStamp::GxTimeStamp()", referenced from:

(null): Kmldom::KmlFactory::CreateGxTimeStamp() const in libLibKML.a(kml_factory.o)

(null): Symbol(s) not found for architecture i386

(null): Linker command failed with exit code 1 (use -v to see invocation)

我可以单独为设备开发,但我希望解决此问题,原因有二:

  • 对于团队来说,有时为了开发目的使用模拟器是很容易的
  • 我真的很想弄清事情的真相,明白为什么在第一种情况下会发生这种情况。尽管目标相同,且目标中包含的源文件在整个模拟器和设备中都相同,但为什么它为设备构建而在模拟器中失败
  • GXTimeStamp和GXTimeSpan类的定义在头文件gx_timeprimitive.h中,其内容如下:

    #ifndef KML_DOM_GX_TIMEPRIMITIVE_H__
    #define KML_DOM_GX_TIMEPRIMITIVE_H__
    
    #include <string>
    #include "kml/base/xml_namespaces.h"
    #include "kml/dom/kml22.h"
    #include "kml/dom/object.h"
    #include "kml/dom/timeprimitive.h"
    
    namespace kmldom {
    
    class Serializer;
    class Visitor;
    
    // <gx:TimeSpan>
    class GxTimeSpan : public TimeSpan {
     public:
      virtual ~GxTimeSpan();
      static KmlDomType ElementType() {
        return Type_GxTimeSpan;
      }
      virtual KmlDomType Type() const { return Type_GxTimeSpan; }
      virtual bool IsA(KmlDomType type) const {
        return type == Type_GxTimeSpan || TimeSpan::IsA(type);
      }
    
      // Visitor API methods, see visitor.h.
      virtual void Accept(Visitor* visitor);
    
     private:
      friend class KmlFactory;
      GxTimeSpan();
      LIBKML_DISALLOW_EVIL_CONSTRUCTORS(GxTimeSpan);
    };
    
    // <gx:TimeStamp>
    class GxTimeStamp : public TimeStamp {
     public:
      virtual ~GxTimeStamp();
      static KmlDomType ElementType() {
        return Type_GxTimeStamp;
      }
      virtual KmlDomType Type() const { return Type_GxTimeStamp; }
      virtual bool IsA(KmlDomType type) const {
        return type == Type_GxTimeStamp || TimeStamp::IsA(type);
      }
    
      // Visitor API methods, see visitor.h.
      virtual void Accept(Visitor* visitor);
    
     private:
      friend class KmlFactory;
      GxTimeStamp();
      LIBKML_DISALLOW_EVIL_CONSTRUCTORS(GxTimeStamp);
    };
    
    }  // end namespace kmldom
    
    #endif  // KML_DOM_GX_TIMEPRIMITIVE_H__
    
    \ifndef KML\u DOM\u GX\u TIMEPRIMITIVE\u H__
    #定义KML\u DOM\u GX\u TIMEPRIMITIVE\u H__
    #包括
    #包括“kml/base/xml_namespaces.h”
    #包括“kml/dom/kml22.h”
    #包括“kml/dom/object.h”
    #包括“kml/dom/timeprimitive.h”
    名称空间kmldom{
    类序列化器;
    班级访客;
    // 
    GxTimeSpan类:公共时间跨度{
    公众:
    虚拟的~GxTimeSpan();
    静态KmlDomType ElementType(){
    返回类型_GxTimeSpan;
    }
    虚拟KmlDomType()常量{return Type_GxTimeSpan;}
    虚拟布尔IsA(KmlDomType类型)常量{
    返回类型==type_GxTimeSpan | | TimeSpan::IsA(类型);
    }
    //访问者API方法,参见Visitor.h。
    虚拟无效接受(访客*访客);
    私人:
    友邦级KML工厂;
    GxTimeSpan();
    LIBKML_不允许邪恶构造函数(GxTimeSpan);
    };
    // 
    类GxTimeStamp:公共时间戳{
    公众:
    虚拟~GxTimeStamp();
    静态KmlDomType ElementType(){
    返回类型_GxTimeStamp;
    }
    虚拟KmlDomType()常量{return Type_GxTimeStamp;}
    虚拟布尔IsA(KmlDomType类型)常量{
    返回类型==type_GxTimeStamp | TimeStamp::IsA(类型);
    }
    //访问者API方法,参见Visitor.h。
    虚拟无效接受(访客*访客);
    私人:
    友邦级KML工厂;
    GxTimeStamp();
    LIBKML_不允许邪恶构造函数(GxTimeStamp);
    };
    }//结束命名空间kmldom
    #endif//KML\u DOM\u GX\u TIMEPRIMITIVE\u H__
    
    我读过很多帖子,说链接器错误是因为源文件没有编译。我也在用同样的思路来解决这个问题,但是我不能将这个头文件包含到编译源代码中,因为它是一个.h文件

    此外,我仔细检查了内部项目的编译源中包含的-kml_factory.cc文件:


    期待您的建议和帮助。谢谢。

    这可能类似于

    以下是最相关的几点:

    在为iOS构建库、框架或应用程序时,XCode将只为目标的构建设置中指定的体系结构编译目标代码。XCode还将仅链接到具有内置指定体系结构的二进制文件

    在iOS模拟器中运行代码时,您是在i386架构的桌面上运行代码

    如果在simluator中运行iOS应用程序时出现缺少i386体系结构错误,则需要确保应用程序及其所有相关库都是为i386体系结构构建的


    这么说让我觉得很愚蠢,但是,我不知道gx_timeprimitive.cc文件是怎么丢失的。我的印象是gx_timeprimitive.h文件本身是完整的,因为它有虚拟类,我试图通过在私有范围中提供构造函数的空实现来定义GXTimeSpan和GXTimeStamp类,如下所示:

    class GxTimeSpan : public TimeSpan {
     public:
      virtual ~GxTimeSpan();
      static KmlDomType ElementType() {
        return Type_GxTimeSpan;
      }
      virtual KmlDomType Type() const { return Type_GxTimeSpan; }
      virtual bool IsA(KmlDomType type) const {
        return type == Type_GxTimeSpan || TimeSpan::IsA(type);
      }
    
      // Visitor API methods, see visitor.h.
      virtual void Accept(Visitor* visitor);
    
     private:
      friend class KmlFactory;
      GxTimeSpan()
      {
    
      }
      LIBKML_DISALLOW_EVIL_CONSTRUCTORS(GxTimeSpan);
    };
    
    但是,编译器仍然不会从接口文件中创建对象文件(.h文件从编译源中排除,它们只包含所有声明),因此链接器无法找到它所需的构造函数。这让我在互联网上搜索gx_timeprimitive.cc文件,它确实是可用的

    冷静思考可以帮我省下100个悬赏点,但我要吸取教训

    此外,为了回答为什么它仅在模拟器模式下出现错误: 实际上,我上面提到的那句话-
    kmldom::PointPtr appPoint=kmlconvence::CreatePointLatLon(appllocation.coordinate.lation,appllocation.coordinate.longitude)
    当为ARMv7构建时,我认为,除非在代码中的其他地方使用变量
    appPoint
    ,否则链接器将跳过将其与libkml对象文件源的链接。然而,i386将执行链接,无论该变量是否在代码中使用。我猜这是某种编译器优化,因为在各自的体系结构中行为是不同的。正是这个谜题让我错过了寻找丢失文件的关键线索

    为那些花时间解决我这个愚蠢问题的人道歉,谢谢大家。


    您使用的是什么版本的XCode?我的代码中包含了libkml源代码,这意味着libkml库将针对在构建主项目之前选择的体系结构进行构建。此外,libkml只依赖于一个外部库——Expat库,我在外部编译了这个库,并创建了一个fat库,它可以跨i386和ARMv7进行链接。此外,Expat库在这里没有给出问题,正如我的问题中所指出的,问题在libkml源代码的某个地方。仍在努力找出问题所在,谢谢你的建议。