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