xcode 将 Objective C 格式的代码转换为纯 C++
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3613310/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Converting Objective C formatted code to pure C++
提问by user436366
I've recently started learning programming to make my own 3D OpenGL game on the iPhone and have made reasonably decent progress so far. I started off using the basic OpenGL example that is provided with the iPhone SDK which helped me get off to a good start. However, as I'm starting to get the hang of things, it has occurred to me that I'm unnecessarily programming in Objective C which will make it harder to port the game to other platforms in the future. So I figured that it would be best to make it properly C++ now to avoid lots of extra work later.
我最近开始学习编程,以便在 iPhone 上制作我自己的 3D OpenGL 游戏,并且到目前为止已经取得了相当不错的进步。我开始使用 iPhone SDK 提供的基本 OpenGL 示例,它帮助我取得了良好的开端。然而,当我开始掌握事情的窍门时,我突然想到我在目标 C 中进行了不必要的编程,这将使未来将游戏移植到其他平台变得更加困难。所以我认为最好现在就使用 C++ 来避免以后的大量额外工作。
To clarify: I'm not actually using any calls to Apple (Objective C) functions or anything, its just that I've based all my clases on the Objective C-style init/dealloc/etc, so that my engine looks like Objective C classes when used. My aim is to replace all the objective C stuff with the C++ equivalents... the trouble is that, being pretty new to C++, I'm not sure what corresponds with what!
澄清一下:我实际上并没有使用任何对 Apple(Objective C)函数或任何东西的调用,只是我的所有类都基于 Objective C 风格的 init/dealloc/etc,所以我的引擎看起来像 Objective使用时的 C 类。我的目标是用 C++ 等价物替换所有目标 C 的东西......问题是,作为 C++ 的新手,我不确定什么对应什么!
Here's a simple example of one of my classes (myLight), in its current Objective C incarnation:
这是我的一个类 (myLight) 的一个简单示例,在其当前的 Objective C 版本中:
// myLight.h
#import <OpenGLES/EAGL.h>
#import <OpenGLES/ES1/gl.h>
#import <OpenGLES/ES1/glext.h>
@interface myLight : NSObject {
char *name;
GLfloat *ambient, *diffuse, *specular, *position, *spotDirection;
GLfloat spotRadius;
GLfloat *matAmbient, *matDiffuse, *matSpecular;
GLfloat shininess;
Byte lightType;
}
@property (readonly) char *name;
@property (assign) GLfloat *position;
@property (assign) GLfloat *spotDirection;
@property (assign) GLfloat *ambient;
@property (assign) GLfloat *diffuse;
@property (assign) GLfloat *specular;
- (id)initWithContentsFromDatastream:(NSData *)fileData;
- (void)set;
@end
And the corresponding .mm file:
以及相应的 .mm 文件:
// myLight.m
#import "myLight.h"
@implementation myLight
@synthesize name, ambient, diffuse, specular, position, spotDirection;
- (id)initWithContentsFromDatastream:(NSData *)fileData {
self = [super init];
NSData *fileContents = fileData;
uint ptr = 0;
Byte nameLength;
[fileContents getBytes:&nameLength range: NSMakeRange(ptr, sizeof(Byte))];
ptr++;
name = new char[nameLength];
[fileContents getBytes:name range: NSMakeRange(ptr, (nameLength * sizeof(char)) )];
ptr = ptr + (nameLength * sizeof(char) );
[fileContents getBytes:&lightType range: NSMakeRange(ptr, sizeof(Byte))];
ptr++;
position = new GLfloat[4];
for(int j = 0; j < (4); j++)
[fileContents getBytes:&position[j] range: NSMakeRange( (j* sizeof(float) ) + ptr, sizeof(float))];
ptr = ptr + (4 * sizeof(float));
if(lightType==2){
spotDirection = new GLfloat[3];
for(int j = 0; j < (3); j++)
[fileContents getBytes:&spotDirection[j] range: NSMakeRange( (j* sizeof(float) ) + ptr, sizeof(float))];
ptr = ptr + (3 * sizeof(float));
[fileContents getBytes:&spotRadius range: NSMakeRange(ptr, sizeof(float))];
ptr = ptr + sizeof(float);
} else
spotDirection = NULL;
diffuse = new GLfloat[4];
for(int j = 0; j < (4); j++)
[fileContents getBytes:&diffuse[j] range: NSMakeRange( (j* sizeof(float) ) + ptr, sizeof(float))];
ptr = ptr + (4 * sizeof(float));
ambient = new GLfloat[4];
for(int j = 0; j < (4); j++)
[fileContents getBytes:&ambient[j] range: NSMakeRange( (j* sizeof(float) ) + ptr, sizeof(float))];
ptr = ptr + (4 * sizeof(float));
specular = new GLfloat[4];
for(int j = 0; j < (4); j++)
[fileContents getBytes:&specular[j] range: NSMakeRange( (j* sizeof(float) ) + ptr, sizeof(float))];
ptr = ptr + (4 * sizeof(float));
[self set];
return self;
}
- (void)set{
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
glLightfv(GL_LIGHT0, GL_POSITION, position);
if(lightType==2)
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, spotDirection);
}
- (void)dealloc {
delete[] specular;
delete[] ambient;
delete[] diffuse;
if (spotDirection)
delete[] spotDirection;
delete[] position;
delete[] name;
[super dealloc];
}
@end
If someone could point out which lines need to be changed and, more importantly, what they should be changed to to make it compile as pure C++, I'd really appreciate it.
如果有人可以指出需要更改哪些行,更重要的是,应该将它们更改为哪些行以使其编译为纯 C++,我将不胜感激。
Many Thanks!
非常感谢!
回答by Alfonso
First of all, please keep in mind that Objective-C is not just a "different format" of C, it's a separate language and more important, in the case of Cocoa, a separate framework. Therefore if you want to be able to port your project to other platforms in the future, you not only have to get rid of Objective-C but also of the Cocoa framework.
首先,请记住,Objective-C 不仅仅是 C 的“不同格式”,它是一种独立的语言,更重要的是,在 Cocoa 的情况下,它是一个独立的框架。因此,如果您希望将来能够将您的项目移植到其他平台,您不仅要摆脱 Objective-C,还必须摆脱 Cocoa 框架。
To map the classes from Objective-C to C++ you would have to do the following:
要将类从 Objective-C 映射到 C++,您必须执行以下操作:
- create a new C++ class to replace the old class
- create constructors for the
-init...
methods - create a destructor for the
-dealloc
method - create other methods which duplicate the functionality
- for properties you would probably create getters and setters instead
- replace the
#import
with#include
directives, as this directive only exists in Objective-C (make sure that the headers you include are protected against multiple includes) - get rid of usages of NS... classes and methods, as those are part of the Cocoa framework and most probably cannot be ported
- 创建一个新的 C++ 类来替换旧的类
- 为
-init...
方法创建构造函数 - 为
-dealloc
方法创建析构函数 - 创建其他复制功能的方法
- 对于属性,您可能会创建 getter 和 setter
- 替换
#import
with#include
指令,因为该指令仅存在于 Objective-C 中(确保您包含的标头受到保护以防止多个包含) - 摆脱 NS... 类和方法的使用,因为它们是 Cocoa 框架的一部分,很可能无法移植
You should take some time to consider how you will use the code you're writing. Porting 1:1 is probably not such a great idea as there are many differences in idioms between coding in Cocoa and C++ (or any other language/framework).
您应该花一些时间考虑如何使用正在编写的代码。移植 1:1 可能不是一个好主意,因为 Cocoa 和 C++(或任何其他语言/框架)中的编码之间的习语存在很多差异。
回答by dreamlax
Most of the applications logic may be translatable to C++, but there are going to be things that have no straightforward equivalent in C++. For example:
大多数应用程序逻辑可能可以翻译成 C++,但有些东西在 C++ 中没有直接的等价物。例如:
- There is no
@encode()
compiler directive (which is used for NSValue and a few other classes). - There is no straightforward equivalent to
doesNotRecognizeSelector:
,respondsToSelector:
,conformsToProtocol:
orperformSelector:
(and other methods of similar nature). - In Objective-C it is fine to send a message to
nil
, but in C++ it is not OK to call a member function on a null pointer. - Objective-C allows extending existing classes using class categories, for example, you can add a method to
NSString
which counts the number of spaces, callednumberOfSpaces
and it will be available for allNSString
instances in your application. - C++ does not have a
finally
block fortry
/catch
, but Objective-C has@finally
for@try
/@catch
.
- 没有
@encode()
编译器指令(用于 NSValue 和一些其他类)。 - 没有直接等同于
doesNotRecognizeSelector:
、respondsToSelector:
、conformsToProtocol:
或performSelector:
(以及其他类似性质的方法)。 - 在 Objective-C 中,可以向 发送消息
nil
,但在 C++ 中,在空指针上调用成员函数是不行的。 - Objective-C 允许使用类类别扩展现有类,例如,您可以添加一个
NSString
计算空格数的方法,调用numberOfSpaces
该方法可用于NSString
应用程序中的所有实例。 - C++ 没有
finally
用于try
/的块catch
,但 Objective-C 有@finally
用于@try
/@catch
。
If you plan on releasing your application to multiple platforms, what you could do is try to abstract as much as you can into a separate library. Your iPhone application can be written in Objective-C and use functions from your library, and if you plan on porting it to another system whose frameworks require C++, then you can write a C++ application and use the same functions from the same library. I imagine your library would basically consist of [at least] your drawing routines and core game engine logic.
如果您计划将您的应用程序发布到多个平台,您可以做的是尝试将尽可能多的内容抽象到一个单独的库中。您的 iPhone 应用程序可以用 Objective-C 编写并使用库中的函数,如果您计划将其移植到框架需要 C++ 的另一个系统,那么您可以编写 C++ 应用程序并使用来自同一库的相同函数。我想你的库基本上由[至少]你的绘图程序和核心游戏引擎逻辑组成。