Yes, that's easily possible, both ways, if you know a few tricks:
1) The "id" type is actually defined in a plain C header. So you can do the following:
In your header:
#include <objc/objc.h>
class MyWindow
{
public:
MyWindow();
~MyWindow();
protected:
id mCocoaWindow;
};
In your implementation (.mm):
#include "MyWindow.h"
#include <Cocoa/Cocoa.h>
MyWindow::MyWindow()
{
mCocoaWindow = [[NSWindow alloc] init];
}
MyWindow::~MyWindow()
{
[mCocoaWindow release];
mCocoaWindow = nil;
}
2) There are two preprocessor constants you can use to exclude C++/ObjC-specific code when a source file includes them that is one of the two, but not ObjC++:
#if __OBJC__
// ObjC code goes here.
#endif /* __OBJC__*/
#if __cplusplus
// C++ code goes here.
#endif
Just be careful, you can't just add/remove ivars or virtual methods with an #ifdef, that will create two classes with different memory layouts and make your app crash in very weird ways.
3) You can use a pointer to a struct without declaring its contents:
In your header:
@interface MyCppObjectWrapper : NSObject
{
struct MyCppObjectWrapperIVars *ivars; // This is straight ObjC, no ++.
}
@end
In your implementation file (.mm):
struct MyCppObjectWrapperIVars
{
std::string myCppString1;
std::string myCppString2;
std::string myCppString3;
};
@implementation MyCppObjectWrapper
-(id) init
{
if(( self = [super init] ))
{
ivars = new MyCppObjectWrapperIVars;
}
return self;
}
-(void) dealloc
{
delete ivars;
ivars = NULL;
[super dealloc];
}
@end
This will make your header simple standard C or ObjC, while your implementation file gets constructors/destructors of all ivars called without you having to create/delete each one as an object on the heap.
This is all only the Mac side of things, but this would mean that you could keep the ObjC stuff out of your headers, or at least make it compile when used from cross-platform client files of the Mac implementation of your C++ portability layer.