将Objective C格式的代码转换为纯C ++

时间:2021-05-02 12:13:40

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示例,这帮助我开始了一个良好的开端。然而,当我开始掌握一些事情时,我发现我在Objective 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!

2 个解决方案

#1


10  

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
  • 创建一个新的C ++类来替换旧类

  • create constructors for the -init... methods
  • 为-init ...方法创建构造函数

  • create a destructor for the -dealloc method
  • 为-dealloc方法创建一个析构函数

  • create other methods which duplicate the functionality
  • 创建其他复制功能的方法

  • for properties you would probably create getters and setters instead
  • 对于属性,您可能会创建getter和setter

  • 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)
  • 用#include指令替换#import,因为此指令仅存在于Objective-C中(确保包含的头文件不受多个包含的影响)

  • get rid of usages of NS... classes and methods, as those are part of the Cocoa framework and most probably cannot be ported
  • 摆脱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 ++(或任何其他语言/框架)中编码之间的习语存在很多差异。

#2


8  

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 ++中会有一些没有直接等价的东西。例如:

  1. There is no @encode() compiler directive (which is used for NSValue and a few other classes).
  2. 没有@encode()编译器指令(用于NSValue和其他一些类)。

  3. There is no straightforward equivalent to doesNotRecognizeSelector:, respondsToSelector:, conformsToProtocol: or performSelector: (and other methods of similar nature).
  4. 没有简单的等效于doesNotRecognizeSelector:,respondsToSelector:,conformsToProtocol:或performSelector :(和其他类似性质的方法)。

  5. 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.
  6. 在Objective-C中,可以将消息发送到nil,但在C ++中,在空指针上调用成员函数是不行的。

  7. Objective-C allows extending existing classes using class categories, for example, you can add a method to NSString which counts the number of spaces, called numberOfSpaces and it will be available for all NSString instances in your application.
  8. Objective-C允许使用类类别扩展现有类,例如,您可以向NSString添加一个方法,该方法计算空间数,称为numberOfSpaces,它将可用于应用程序中的所有NSString实例。

  9. C++ does not have a finally block for try/catch, but Objective-C has @finally for @try/@catch.
  10. C ++没有try / catch的finally块,但是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 ++应用程序并使用相同库中的相同函数。我想你的库基本上包括[至少]你的绘图例程和核心游戏引擎逻辑。

#1


10  

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
  • 创建一个新的C ++类来替换旧类

  • create constructors for the -init... methods
  • 为-init ...方法创建构造函数

  • create a destructor for the -dealloc method
  • 为-dealloc方法创建一个析构函数

  • create other methods which duplicate the functionality
  • 创建其他复制功能的方法

  • for properties you would probably create getters and setters instead
  • 对于属性,您可能会创建getter和setter

  • 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)
  • 用#include指令替换#import,因为此指令仅存在于Objective-C中(确保包含的头文件不受多个包含的影响)

  • get rid of usages of NS... classes and methods, as those are part of the Cocoa framework and most probably cannot be ported
  • 摆脱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 ++(或任何其他语言/框架)中编码之间的习语存在很多差异。

#2


8  

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 ++中会有一些没有直接等价的东西。例如:

  1. There is no @encode() compiler directive (which is used for NSValue and a few other classes).
  2. 没有@encode()编译器指令(用于NSValue和其他一些类)。

  3. There is no straightforward equivalent to doesNotRecognizeSelector:, respondsToSelector:, conformsToProtocol: or performSelector: (and other methods of similar nature).
  4. 没有简单的等效于doesNotRecognizeSelector:,respondsToSelector:,conformsToProtocol:或performSelector :(和其他类似性质的方法)。

  5. 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.
  6. 在Objective-C中,可以将消息发送到nil,但在C ++中,在空指针上调用成员函数是不行的。

  7. Objective-C allows extending existing classes using class categories, for example, you can add a method to NSString which counts the number of spaces, called numberOfSpaces and it will be available for all NSString instances in your application.
  8. Objective-C允许使用类类别扩展现有类,例如,您可以向NSString添加一个方法,该方法计算空间数,称为numberOfSpaces,它将可用于应用程序中的所有NSString实例。

  9. C++ does not have a finally block for try/catch, but Objective-C has @finally for @try/@catch.
  10. C ++没有try / catch的finally块,但是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 ++应用程序并使用相同库中的相同函数。我想你的库基本上包括[至少]你的绘图例程和核心游戏引擎逻辑。