![](/img/trans.png)
[英]How do I compile + link C++ code in Xcode in an Objective-C project?
[英]Can I separate C++ main function and classes from Objective-C and/or C routines at compile and link?
我有一个小的C ++应用程序,我导入了Objective-C类。 它可用作Objective-C ++文件,.mm,但任何包含可能最终包含某些Objective-C标头的标头的C ++文件必须重命名为.mm扩展名,以获取正确的GCC驱动程序。
有没有办法为Objective-C类编写一个纯粹的C ++包装器,或者我可以将Objective-C对象分开,并将它们分开链接? 也许即使Objective-C类成为一个小型库,我可以在编译时静态重新链接?
问题是这个代码是跨平台的,并且在通常不使用Objective-C(即不是Mac)的系统上编译更加困难。 即使预处理器命令限制在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”类型实际上是在普通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或虚拟方法,这将创建具有不同内存布局的两个类,并使您的应用程序以非常奇怪的方式崩溃。
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的构造函数/析构函数,而无需创建/删除每个作为堆上的对象。
这只是Mac方面的事情,但这意味着您可以将ObjC内容保留在标题之外,或者至少在从C ++可移植性层的Mac实现的跨平台客户端文件中使用时进行编译。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.