【问题标题】:Converting Objective C formatted code to pure C++将 Objective C 格式的代码转换为纯 C++
【发布时间】:2011-04-06 12:18:09
【问题描述】:

我最近开始学习编程以在 iPhone 上制作我自己的 3D OpenGL 游戏,并且到目前为止取得了相当不错的进展。我开始使用 iPhone SDK 提供的基本 OpenGL 示例,它帮助我有了一个良好的开端。然而,当我开始掌握事情的窍门时,我突然想到我在 Objective C 中进行了不必要的编程,这将使将来将游戏移植到其他平台变得更加困难。所以我想现在最好把它变成正确的 C++ 以避免以后做很多额外的工作。

澄清一下:我实际上并没有使用任何对 Apple(Objective C)函数或任何东西的调用,只是我所有的类都基于 Objective C 风格的 init/dealloc/etc,所以我的引擎使用时看起来像 Objective C 类。我的目标是用 C++ 等价物替换所有客观的 C 东西......问题是,对于 C++ 来说还很新,我不确定什么对应于什么!

这是我的一个类 (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

以及对应的.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

如果有人能指出需要更改哪些行,更重要的是,应该将它们更改为什么以使其编译为纯 C++,我将不胜感激。

非常感谢!

【问题讨论】:

  • Err... 对于很多这样的事情,没有没有 C++ 等价物。 IE。 “属性”两者的对象模型完全不同。
  • 这几乎是不可能的。 iPhone 使用 Objective-C 作为所有 iPhone 应用程序的 GUI 框架,用 C++ 替换它是不可能的,因为没有 C++ 替代 GUI 框架,因此你不会有任何图形。但这样做实际上使代码更容易移植到其他平台,因为 GUI 代码很容易与底层引擎(希望用 C++ 编写)区分开来。所以你只需要为你必须做的每个平台重新编写 GUI。 Note: easier not easy.
  • Billy 是对的,但要更进一步:标题的几乎每一行都需要更改,并且您的实现文件也有相当一部分。 C++ 和 Objective-C 有非常不同的语法。不过,程序逻辑(例如 if(lightType==2))和对 OpenGL 的调用(例如 glEnable(GL_LIGHTING))都可以,因为它们是纯 C 语言,通常直接转换为 C++。
  • 是的,我最初确实低估了任务的范围,因为我可能确实认为有些事情会更加一对一地等效。也就是说,我很确定它不会“几乎不可能”......只是不像我希望的那么容易!不管怎样,谢谢你的建议,不胜感激。

标签: c++ iphone objective-c xcode


【解决方案1】:

首先,请记住,Objective-C 不仅仅是 C 的“不同格式”,它是一种独立的语言,更重要的是,对于 Cocoa,它是一个独立的框架。因此,如果您希望将来能够将您的项目移植到其他平台,您不仅要摆脱 Objective-C,还要摆脱 Cocoa 框架。

要将类从 Objective-C 映射到 C++,您必须执行以下操作:

  • 创建一个新的 C++ 类来替换旧的类
  • -init... 方法创建构造函数
  • -dealloc 方法创建析构函数
  • 创建其他复制功能的方法
  • 对于您可能会创建 getter 和 setter 的属性
  • #import 替换为#include 指令,因为该指令仅存在于Objective-C 中(确保您包含的标头受到保护以防止多次包含)
  • 摆脱对 NS... 类和方法的使用,因为它们是 Cocoa 框架的一部分,很可能无法移植

您应该花一些时间考虑如何使用您正在编写的代码。移植 1:1 可能不是一个好主意,因为 Cocoa 和 C++(或任何其他语言/框架)编码之间的习语有很多差异。

【讨论】:

  • 感谢您提供非常有用的答案。我知道你提到的一些问题,但我真的很欣赏这些细节。我天真地期望仍然能够在我的 C++ 代码中使用 NS* 类(当然,尽管仅适用于 MacOS),所以这对我来说也是新闻!无论如何,我会尝试再考虑一下。谢谢您的建议!
  • 当然不客气 :-) 请注意:如果您的代码只能在 Mac OS X 上运行,您仍然可以在 C++ 代码中使用 NS* 类(它实际上是 Objective-C++ 代码然后,但这由编译器静默处理)。当我提到摆脱 NS* 类时,我指的是您问题的“将代码移植到另一个平台”部分。
  • 嗯,明白了。所以你可以使用 NS* 类..?如何..? (如果你不介意简单解释一下!)
  • 您可以像在纯 Objective-C 中一样使用它们。据我所知,对于混合 C++ 和 Objective-C 的文件,您必须使用以 .mm 结尾的文件,否则编译器可能无法识别该语言。但是如果你这样做,你将你的代码绑定到 OS X 平台,并且如果你在你的头文件中公开任何 Objective-C 类,那么使用你的类的代码也必须使用 Objective-C++。
  • 啊,很好,至少那按预期工作!太好了,再次感谢!
【解决方案2】:

大多数应用程序逻辑都可以转换为 C++,但有些东西在 C++ 中没有直接的等价物。例如:

  1. 没有@encode() 编译器指令(用于 NSValue 和其他一些类)。
  2. 没有直接等效于doesNotRecognizeSelector:respondsToSelector:conformsToProtocol:performSelector:(以及其他类似性质的方法)。
  3. 在 Objective-C 中,可以向 nil 发送消息,但在 C++ 中,不能在空指针上调用成员函数。
  4. Objective-C 允许使用类类别扩展现有的类,例如,您可以向NSString 添加一个计算空格数的方法,称为numberOfSpaces,它将可用于您的所有NSString 实例申请。
  5. C++ 没有finally 块用于try/catch,但Objective-C 有@finally 用于@try/@catch

如果您计划将应用程序发布到多个平台,您可以尝试将尽可能多的内容抽象到单独的库中。您的 iPhone 应用程序可以用 Objective-C 编写并使用您的库中的函数,如果您计划将其移植到另一个其框架需要 C++ 的系统,那么您可以编写一个 C++ 应用程序并使用同一个库中的相同函数。我想您的库基本上将包含[至少]您的绘图例程和核心游戏引擎逻辑。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-08
    相关资源
    最近更新 更多