Преобразование кода, отформатированного в Objective C, в чистый C ++ - PullRequest
4 голосов
/ 01 сентября 2010

Я недавно начал изучать программирование для создания своей собственной 3D-игры OpenGL на iPhone и до сих пор добился довольно приличного прогресса. Я начал с использования базового примера OpenGL, который поставляется с iPhone SDK, что помогло мне хорошо начать. Тем не менее, когда я начинаю изучать ситуацию, мне пришло в голову, что я излишне программирую на 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 ++, я был бы очень признателен.

Большое спасибо!

Ответы [ 2 ]

10 голосов
/ 01 сентября 2010

Прежде всего, имейте в виду, что Objective-C - это не просто «другой формат» языка C, это отдельный язык и, что более важно, в случае с Cocoa, отдельная структура. Поэтому, если вы хотите иметь возможность портировать свой проект на другие платформы в будущем, вам нужно избавиться не только от Objective-C, но и от среды Cocoa.

Чтобы отобразить классы из Objective-C в C ++, вам нужно сделать следующее:

  • создать новый класс C ++ для замены старого класса
  • создание конструкторов для -init... методов
  • создать деструктор для метода -dealloc
  • создать другие методы, дублирующие функциональность
  • для свойств вы, вероятно, вместо этого создадите геттеры и сеттеры
  • замените директивы #import на #include, так как эта директива существует только в Objective-C (убедитесь, что заголовки, которые вы включаете, защищены от нескольких включений)
  • избавиться от использования классов и методов NS ..., поскольку они являются частью инфраструктуры Какао и, скорее всего, не могут быть портированы

Вам нужно потратить некоторое время, чтобы подумать, как вы будете использовать код, который пишете. Портирование 1: 1, вероятно, не такая уж хорошая идея, поскольку существует много различий в идиомах между кодированием в Cocoa и C ++ (или любом другом языке / фреймворке).

8 голосов
/ 01 сентября 2010

Большая часть логики приложений может быть переведена на 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 ++ и использовать те же функции из той же библиотеки. Я полагаю, что ваша библиотека в основном будет состоять из [по крайней мере] ваших процедур рисования и базовой логики игрового движка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...