我在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
答案 0 :(得分: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
请注意,在编译.mm文件时,会定义__OBJC__和__cplusplus。 #include和#import在Objective-C(C-99的超集)中大致相同,但是你必须对C / C ++可见的任何东西使用#include。
请记住,在C中,一个永远没有定义foo的struct foo*
(指向匿名结构的指针)是一个完全有效的类型,所以它的作用是将“其他语言类”命名为匿名结构,你可以传递给它指针没有看内容。
我将作为练习留下如何与ARC交互ObjC实例变量。 (可能有龙和/或你可能需要__unsafe_unretained)
IIRC,如果您使用与C ++类相同的结构名称,调试器将显示正确的信息(如果它可用)。我不确定这对Obj-C是否安全,所以我使用了不同的名字。
另外,尽量避免包含C ++标头(只需将它包含在.mm实现文件中),除非您需要匿名类以外的类型。或者,您可以为它创建一个看起来像此文件顶部的包装器标头。
HTH,-Steve
答案 1 :(得分:3)
Objective-C ++是一个病毒式的东西,你无法真正停止。您当前的示例为您的代码的不同部分(C和C ++)提供了类的布局的不同视图,虽然我认为它仍然可以工作,但我很确定这不是一件好事。
当处理与C ++交互的ObjC项目时,我通常会尽量避免在头文件中使用C ++引用。这使得头文件对Objective-C和Objective-C ++都有效。如果我无法避免它,那么我就不会试图对抗它(这是一个失败的原因);但我尝试不将ObjC ++头文件包含在其他“理智”的ObjC头文件中,并且我使用@class
指令(@class SomeObjCPPClass;
而不是#import "SomeObjCPPClass.h"
指令)代替我需要引用班级。然后,我包含来自实现文件的头文件,它必须是ObjC ++,但至少它不会从那里传播。
编辑最新版本的Clang(2012及更高版本)允许您在@implementation
方面声明字段。这可以有效地释放您对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
// SomeClass.mm
#import "CPlusPlusLibrary.h"
@implementation SomeClass
{
CPlusPlusClass* variable;
}
// (method implementations)
@end
这使SomeClass.h标头安全地包含在纯Objective-C文件和Objective-C ++文件中。
答案 2 :(得分:1)
在编译为c ++时有一个预定义的宏定义:__cplusplus
我猜对于目标c ++也是如此。