我可以在编译和链接中将C ++ main函数和类从Objective-C和/或C例程中分离出来吗?

我有一个小型的C ++应用程序,我导入了Objective-C类。 它可以用作Objective-C ++文件.mm,但是包含可能最终包含一些Objective-C头文件的头文件的任何C ++文件都必须重命名为适合GCC驱动程序的.mm扩展名。

有没有办法为Objective-C类编写纯粹的C ++包装器,或者我可以以某种方式将Objective-C对象分开,并将它们分开链接起来? 也许即使Objective-C类成为一个小型库,我可以在编译时静态地重新链接?

问题是这个代码是跨平台的,在通常不使用Objective-C(即不是Mac)的系统上编译更加困难。 尽pipe预处理器命令限制了在Windows或Linux上Objective-C代码的任何实现,但原始代码仍然具有.mm扩展名,而GCC仍然将代码视为Objective-C ++。

通常你只需用C ++类包装你的Objective-C类,例如使用不透明的指针并将调用转换为C ++方法到Objective-C方法。

这样,您的便携式C ++源码永远不需要看到任何Objective-C包含,理想情况下,您只需要在不同平台上交换包装器的实现文件。

例:

// 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]; } // ... 

是的,如果你知道一些技巧,那么这两种方法都是可能的:

1)“id”types实际上是在普通的C头文件中定义的。 所以你可以做到以下几点:

在你的标题中:

 #include <objc/objc.h> class MyWindow { public: MyWindow(); ~MyWindow(); protected: id mCocoaWindow; }; 

在你的实现(.mm)中:

 #include "MyWindow.h" #include <Cocoa/Cocoa.h> MyWindow::MyWindow() { mCocoaWindow = [[NSWindow alloc] init]; } MyWindow::~MyWindow() { [mCocoaWindow release]; mCocoaWindow = nil; } 

2)有两个预处理常量可以用来排除C ++ / ObjC特定的代码,当一个源文件包含它们是两个之一,但不是ObjC ++:

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

只要小心,你不能只用#ifdef添加/删除ivars或虚拟方法,这将创build两个具有不同内存布局的类,并以非常怪异的方式使你的应用程序崩溃。

3)您可以使用指向结构体的指针而不声明其内容:

在你的标题中:

 @interface MyCppObjectWrapper : NSObject { struct MyCppObjectWrapperIVars *ivars; // This is straight ObjC, no ++. } @end 

在您的实施文件(.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 

这将使您的标题简单的标准C或ObjC,而你的实现文件获取调用所有ivars的构造函数/析构函数,而不必创build/删除每个堆作为一个对象。

这仅仅是Mac的一部分,但是这意味着你可以将ObjC的东西保存在你的头文件中,或者至less在从C ++可移植层的Mac实现的跨平台客户端文件中进行编译时进行编译。