Can I separate the main function and C ++ classes from Objective-C and / or C routines when compiling and linking?

I have a small C ++ application into which I imported Objective-C classes. It works as Objective-C ++ files, .mm, but any C ++ file that includes a header that may eventually contain some Objective-C header should be renamed to the .mm extension for the correct GCC drivers.

Is there a way to write a pure C ++ wrapper for Objective-C classes, or can I somehow isolate Objective-C objects and just bind them separately? Maybe even if the Objective-C classes became a small library, could I statically reassign at compile time?

The problem is that this code is cross-platform, and it is harder to compile on systems that usually do not use Objective-C (i.e. not a Mac). Although preprocessor commands restrict any implementation of Objective-C code on Windows or Linux, the source code still has .mm extensions, and GCC still treats the code as Objective-C ++.

+6
c ++ compiler-construction objective-c objective-c ++
source share
2 answers

Usually you just port Objective-C classes to C ++ classes, for example. using opaque pointers and redirecting calls to C ++ methods to Objective-C methods.

Thus, your portable C ++ sources should never see what any Objective-C includes, and ideally you only need to exchange implementation files for wrappers on different platforms.

Example:

// c++ header: class Wrapper { struct Opaque; Opaque* opaque; // ... public: void f(); }; // Objective-C++ source on Mac: struct Wrapper::Opaque { id contained; // ... }; void Wrapper::f() { [opaque->contained f]; } // ... 
+3
source share

Yes, it is easily possible, in both directions, if you know a few tricks:

1) The type "id" is actually defined in a regular C-header. So you can do the following:

In the title:

 #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 that you can use to exclude C ++ / ObjC code when the source file includes those that are one of two, but not ObjC ++:

 #if __OBJC__ // ObjC code goes here. #endif /* __OBJC__*/ #if __cplusplus // C++ code goes here. #endif 

Just be careful, you cannot just add / remove ivars or virtual methods using #ifdef, which will create two classes with different memory layouts and make your application crash very strange.

3) You can use a pointer to a structure without declaring its contents:

In the title:

 @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 a simple C or ObjC standard, while your implementation file receives the constructors / destructors of all the iWars, which are called without having to create / delete them as an object on the heap.

This is just the Mac side, but that would mean that you could save ObjC stuff from your headers or at least compile it when using your C ++ portability cross-platform client implementation Mac files.

+2
source share

All Articles