开发者

How to detect C++ compiler with macro in Xcode?

I'm mixing Objective-C (*.m) and Objective-C++ (*.mm) source files in an iOS project. When I import a C++ header file in a *.m file how can I exclude the C++-specific code 开发者_如何学编程in the header file? I want to use a compiler macro, something like:

// 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


That would fail badly because an instance of SomeClass would have a different size and layout depending on whether it's compiled from a .m or a .mm file.

Here's what I would do (with added code to make it includable from .c and .cp as well):

#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

Note that when compiling a .mm file, both __OBJC__ and __cplusplus are defined. #include and #import are roughly equivalent in Objective-C (a superset of C-99), but you must use #include for anything visible to C/C++.

Remember that in C, a struct foo* with foo never defined (pointer to anonymous structure) is a perfectly valid type, so what this does is typedef "other language classes" as anonymous structs which you can pass around by pointer w/o looking at the contents.

I'll leave as an exercise how this interacts with ARC for ObjC instance variables. (There might be dragons and/or you may need __unsafe_unretained)

IIRC, if you use the same name for the struct as the C++ class, the debugger will show the right information if it has it available. I'm not sure if that's safe for Obj-C so I used a different name.

Also, try to avoid including the C++ header (just #include it in your .mm implementation file) unless you need it for types other than the anonymous class. Alternatively, you might create a wrapper header for it that looks like the top of this file.

HTH, -Steve


Objective-C++ is a viral thing that you can't really stop. Your current example gives different parts of your code (C and C++) a different view of the layout of your class, and while I do think it would still work, I'm pretty sure this isn't a very good thing.

When working on ObjC projects interacting with C++, I usually try to avoid having C++ references in my header files. This makes the header file valid for both Objective-C and Objective-C++. If I can't avoid it, then I don't try to fight it (it's a lost cause); but I try to not include that ObjC++ header file in otherwise 'sane' ObjC headers, and I use the @class directive (@class SomeObjCPPClass; instead of an #import "SomeObjCPPClass.h" directive) instead if I need to reference the class. Then, I include the header from the implementation file, which has to be ObjC++, but at least it won't propagate from there.

EDIT Recent-ish (2012 and later) versions of Clang allow you to declare fields in the @implementation side of things. This can effectively free your header of any references to C++ and make Objective-C++ much more manageable (and less viral). To retain OP's example, you would now have:

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

@interface SomeClass : BaseClass

// (no fields)

// (methods)

@end

// SomeClass.mm
#import "CPlusPlusLibrary.h"

@implementation SomeClass
{
    CPlusPlusClass* variable;
}

// (method implementations)

@end

This makes the SomeClass.h header safe to include in pure Objective-C files and Objective-C++ files as well.


There is a predefined macro that's defined when compiling as c++: __cplusplus I'd guess the same is true for objective c++.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜