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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With