我想编写使用C++和Cocoa框架的应用程序,因为Apple不支持使用Carbon 64位.C++在Linux和Windows上的实现似乎相当普遍,但在Mac OS X上似乎需要额外的Apple特定代码片段(如Obj-C包装器).苹果似乎也在强迫开发人员用Objective-C而不是C++编写,尽管我可能错了.
我试图找到一条在Mac上编写代码的路径,这种代码很容易保持跨平台.必须用C++ for Linux/Windows编写代码,然后在Objective-C中重写大部分代码效率非常低.
有没有办法用C++编写代码,这些代码将来会得到支持并在Xcode中得到支持?另外,如果可以的话,我如何在Xcode中混合使用C++和Objective-C?谢谢.
你不能完全用C++编写Cocoa应用程序.Cocoa很大程度上依赖于Objective-C的许多核心技术的后期绑定功能,例如Key-Value Bindings,委托(Cocoa风格)和目标 - 动作模式.后期绑定要求使得在C++中编译时绑定的类型语言中实现Cocoa API 非常困难.当然,您可以编写一个在OS X上运行的纯C++应用程序.它不能使用Cocoa API.
因此,如果要在其他平台上的C++应用程序和基于Cocoa的应用程序之间共享代码,则有两种选择.第一种是用C++编写模型层,用Cocoa编写GUI.这是一些非常大的应用程序(包括Mathematica)使用的常用方法.您的C++代码可以保持不变(您不需要"funky"apple扩展来在OS X上编写或编译C++).您的控制器层可能会使用Objective-C++(可能是您所指的"时髦"Apple扩展).Objective-C++是C++的超集,正如Objective-C是C的超集一样.在Objective-C++中,您可以[some-objc-object callMethod];
在C++函数中进行objc样式的消息传递调用(如).相反,您可以从ObjC代码中调用C++函数,如:
@interface MyClass { MyCPPClass *cppInstance; } @end @implementation MyClass - (id)init { if(self = [super init]) { cppInstance = new MyCPPClass(); } return self; } - (void) dealloc { if(cppInstance != NULL) delete cppInstance; [super dealloc]; } - (void)callCpp { cppInstance->SomeMethod(); } @end
您可以在Objective-C语言指南中找到有关Objective-C++的更多信息.然后视图层可以是纯Objective-C.
第二种选择是使用跨平台的C++工具包.在Qt的工具包可能适合该法案.跨平台工具包通常被Mac用户鄙视,因为他们没有完全正确地获得所有外观和感觉细节,并且Mac用户希望在Mac应用程序的UI中得到润色.然而,Qt做得非常出色,根据观众和应用程序的使用情况,它可能已经足够好了.此外,您将失去一些特定于OS X的技术,例如Core Animation和一些QuickTime功能,尽管Qt API中有大致替代品.正如您所指出的,Carbon不会被移植到64位.由于Qt是在Carbon API上实现的,因此Trolltech/Nokia不得不将Qt移植到Cocoa API以使其与64位兼容.我的理解是Qt的下一个关系(目前正在发布中)完成此转换并在OS X上与64位兼容.如果您对集成C++和Cocoa API感兴趣,可能需要查看Qt 4.5的源代码.
ⁱ有一段时间Apple将Cocoa API提供给Java,但是这个桥需要大量的手动调整,并且无法处理更高级的技术,例如上面描述的Key-Value Bindings.目前,动态类型化的运行时绑定语言(如Python,Ruby等)是编写没有Objective-C的Cocoa应用程序的唯一真正选择(当然这些桥梁使用了Objective-C).
嗯,这可能听起来很愚蠢,但实际上我们可以编写纯C++代码来为Mac OS X创建GUI,但我们必须链接到Cocoa框架.
/* * test1.cpp * This program shows how to access Cocoa GUI from pure C/C++ * and build a truly functional GUI application (although very simple). * * Compile using: * g++ -framework Cocoa -o test1 test1.cpp * * that will output 'test1' binary. */ #include#include #include #include extern "C" int NSRunAlertPanel(CFStringRef strTitle, CFStringRef strMsg, CFStringRef strButton1, CFStringRef strButton2, CFStringRef strButton3, ...); int main(int argc, char** argv) { id app = NULL; id pool = (id)objc_getClass("NSAutoreleasePool"); if (!pool) { std::cerr << "Unable to get NSAutoreleasePool!\nAborting\n"; return -1; } pool = objc_msgSend(pool, sel_registerName("alloc")); if (!pool) { std::cerr << "Unable to create NSAutoreleasePool...\nAborting...\n"; return -1; } pool = objc_msgSend(pool, sel_registerName("init")); app = objc_msgSend((id)objc_getClass("NSApplication"), sel_registerName("sharedApplication")); NSRunAlertPanel(CFSTR("Testing"), CFSTR("This is a simple test to display NSAlertPanel."), CFSTR("OK"), NULL, NULL); objc_msgSend(pool, sel_registerName("release")); return 0; }
是的,你可以只使用C++(即用*.cpp文件编写),甚至在*.mm文件中混合使用C++和Objective-C(标准Objective-C代码存储在*.m文件中).
当然,您仍然必须使用Objective-C作为用户界面并为C++对象创建Objective-C包装器.另一个选择是切换到Qt,这是一个支持Windows,Mac OS X和Linux的C++ Framework - 并将在LGPL下发布,下一个版本为4.5.
是的你可以混合它们.
您需要使用Objective-C直接操作GUI对象并接收来自它们的通知.
如果将这些Objective-C对象放在.mm文件中,而不是纯粹的Objective-C .m文件,它们可以直接调用C++逻辑.请注意,您可能会看到(很多)较旧的建议,建议使用大写.M来表示Objective-C++,但这非常不稳定,可能会让您和编译器混淆.
您不需要包装每个C++对象,但您的Objective-C代码将需要包含指向它们的指针.
Apple不再发布任何显示如何执行此操作的示例.
Peter Steinberger在Realm上主持了很棒的视频[目的] C++:可能出错的是什么?我强烈推荐任何仍然使用Objective-C++的人,你可以快速浏览成绩单.