如何在Xcode中用宏检测C++编译器?

Fel*_*lix 4 c++ macros xcode objective-c objective-c++

我在iOS项目中混合了Objective-C(*.m)和Objective-C++(*.mm)源文件.当我在*.m文件中导入C++头文件时,如何在头文件中排除C++特定的代码?我想使用编译器宏,如:

// SomeClass.h - a file I want to import in C++ and Objectice-C classes

#if CPLUSPLUS
#import "CPlusPlusLibrary.h"
#endif 

@interface SomeClass : BaseClass
{

#if CPLUSPLUS
  CPlusPlusClass* variable;
#endif    

}

@end
Run Code Online (Sandbox Code Playgroud)

Ste*_*sak 8

那会很糟糕,因为SomeClass的实例会有不同的大小和布局,具体取决于它是从.m还是.mm文件编译而来.

这就是我要做的事情(使用添加的代码使其可以从.c和.cp中包含):

#ifdef __OBJC__
    #import <Foundation/Foundation.h>
#endif

#ifdef __cplusplus
    #include "CPlusPlusLibrary.h"
#endif

#ifdef __cplusplus
    class CPlusPlusClass;
#else
    typedef struct CPlusPlusClass CPlusPlusClass;
#endif

#ifdef __OBJC__
    @class AnotherObjCClass;
    @interface SomeObjCClass : NSObject
    {
        CPlusPlusClass* _variableCPP;
        AnotherObjCClass* _variableObjC;
    }
#else
    typedef struct ObjC_AnotherObjCClass AnotherObjCClass;
    typedef struct ObjC_SomeClass SomeObjCClass;
#endif

#ifdef __cplusplus
extern "C" { // Callable from C
#endif   
    void CFunctionTakingCPlusPlusClass(CPlusPlusClass* foo);
    void CFunctionTakingSomeObjCClass(SomeObjCClass* foo);      
#ifdef __cplusplus
}
#endif
Run Code Online (Sandbox Code Playgroud)

请注意,在编译.mm文件时,会定义__OBJC__和__cplusplus.#include和#import在Objective-C(C-99的超集)中大致相同,但是你必须对C/C++可见的任何东西使用#include.

请记住,在C中,struct foo*foo永远不会定义(指向匿名结构的指针)是一个完全有效的类型,所以它的作用是将"其他语言类"作为匿名结构,你可以通过指针传递来查看内容.

我将作为练习留下如何与ARC交互ObjC实例变量.(可能有龙和/或你可能需要__unsafe_unretained)

IIRC,如果您使用与C++类相同的结构名称,调试器将显示正确的信息(如果它可用).我不确定这对Obj-C是否安全,所以我使用了不同的名字.

另外,尽量避免包含C++标头(只需将它包含在.mm实现文件中),除非您需要匿名类以外的类型.或者,您可以为它创建一个类似于此文件顶部的包装器标头.

HTH,-Steve


zne*_*eak 3

Objective-C++ 是一种你无法真正阻止的病毒式传播。您当前的示例为代码的不同部分(C 和 C++)提供了类布局的不同视图,虽然我确实认为它仍然有效,但我很确定这不是一件好事。

在处理与 C++ 交互的 ObjC 项目时,我通常会尝试避免在头文件中包含 C++ 引用。这使得头文件对 Objective-C 和 Objective-C++ 都有效。如果我无法避免它,那么我就不会尝试去对抗它(这是一个失败的原因);但我尝试不将 ObjC++ 头文件包含在其他“正常”的 ObjC 标头中,并且如果需要引用该类,我会使用@class指令(@class SomeObjCPPClass;而不是指令)。#import "SomeObjCPPClass.h"然后,我包含实现文件中的标头,该标头必须是 ObjC++,但至少它不会从那里传播。

编辑@implementationClang 的最新版本(2012 及更高版本)允许您在事物侧面声明字段。这可以有效地释放您的标头中对 C++ 的任何引用,并使 Objective-C++ 更易于管理(并且更少传播)。要保留 OP 的示例,您现在将拥有:

// SomeClass.h - a file I want to import in C++ and Objectice-C classes

@interface SomeClass : BaseClass

// (no fields)

// (methods)

@end
Run Code Online (Sandbox Code Playgroud)
// SomeClass.mm
#import "CPlusPlusLibrary.h"

@implementation SomeClass
{
    CPlusPlusClass* variable;
}

// (method implementations)

@end
Run Code Online (Sandbox Code Playgroud)

这使得 SomeClass.h 头文件也可以安全地包含在纯 Objective-C 文件和 Objective-C++ 文件中。