облегчить переход с ++ на цель-c / какао с помощью метапрограммирования? - PullRequest
34 голосов
/ 17 февраля 2010

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

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

Если вам приходится иметь дело с интерфейсами нетривиального размера и вы хотите избежать генерации кода на основе сценариев, это быстро становится громоздким и вызывает боль каждый раз, когда необходимо проводить рефакторинг. Используя комбинацию (шаблонного) метапрограммирования и библиотеки времени выполнения Objective C, можно значительно сократить объем кода ...

Прежде чем я начну изобретать велосипед (и, возможно, потрачу время) , кто-нибудь знает о методах, лучших практиках или примерах в этом направлении?


Как в примере, скажем, нам нужен делегат, который поддерживает этот неофициальный протокол:

- (NSString*)concatString:(NSString*)s1 withString:(NSString*)s2;
- (NSNumber*)     indexOf:(CustomClass*)obj;

Вместо реализации класса Obj-C, который теперь явно связан с экземпляром C ++, я хотел бы сделать что-то вроде этого вместо этого:

class CppObj {
    ObjcDelegate m_del;
public:
    CppObj() : m_del(this) 
    {
        m_del.addHandler
            <NSString* (NSString*, NSString*)>
            ("concatString", &CppObj::concat);
        m_del.addHandler
            <NSNumber* (CustomClass*)>
            ("indexOf", &CppObj::indexOf);
    }

    std::string concat(const std::string& s1, const std::string& s2) {
        return s1.append(s2);
    }

    size_t indexOf(const ConvertedCustomClass& obj) {
        return 42;
    }
};

Все, что может потребоваться пользователю для поддержки дополнительных типов, - это специализировать функцию шаблона преобразования:

template<class To, class From> To convert(const From&);

template<> 
NSString* convert<NSString*, std::string>(const std::string& s) { 
    // ...
}

// ...

В приведенном выше примере, конечно, игнорируется поддержка формальных протоколов и т. Д., Но суть должна быть понятна. Кроме того, из-за того, что информация о типах для Objc-runtime-типов в основном распадалась на some-native-types или class-type , я не думаю, что явная спецификация параметра и возвращаемых типов для делегата- методов можно избежать.

Ответы [ 2 ]

5 голосов
/ 05 марта 2010

Я не нашел ничего удовлетворительного и придумал прототип, который, учитывая следующий неофициальный протокол:

- (NSString*)concatString:(NSString*)s1 withString:(NSString*)s2;

и этот код C ++:

struct CppClass {
    std::string concatStrings(const std::string& s1, const std::string& s2) const {
        return s1+s2;
    }
};

std::string concatStrings(const std::string& s1, const std::string& s2) {
    return s1+s2;
}

позволяет создать и передать делегата:

CppClass cpp;
og::ObjcClass objc("MyGlueClass");
objc.add_handler<NSString* (NSString*, NSString*)>
    ("concatString:withString:", &cpp, &CppClass::concatStrings);
// or using a free function:
objc.add_handler<NSString* (NSString*, NSString*)>
    ("concatString:withString:", &concatStrings);
[someInstance setDelegate:objc.get_instance()];

, который затем может быть использован:

NSString* result = [delegate concatString:@"abc" withString:@"def"];
assert([result compare:@"abcdef"] == NSOrderedSame);

Boost.Function объекты также могут быть переданы, что означает, что Boost.Bind также может легко использоваться.

Хотя основная идея работает, это все еще прототип. Я сделал небольшое сообщение в блоге на эту тему, и источник прототипа доступен через bitbucket . Конструктивный вклад и идеи приветствуются.

4 голосов
/ 22 февраля 2010

Вы смотрели библиотеку wxWidgets? Я не пишу код в Objective-C, но, по крайней мере, разработчики требуют достойной поддержки Cocoa / Objective-C. Это означает, что у них есть какое-то отображение из C ++, реализованное как-то. Веб-сайт библиотеки: http://www.wxwidgets.org.

...