Подтвердить что ты не робот

Упрощение С++ до objective-c/cocoa моста через метапрограммирование?

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

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

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

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


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

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

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

4b9b3361

Ответ 1

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

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

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

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 также может быть легко использован.

Пока основная идея работает, это все еще прототип. Я сделал короткое сообщение по этому вопросу и источник прототипа доступен через битбакет. Конструктивные идеи и идеи приветствуются.

Ответ 2

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