通过元编程缓解C ++到Objective-C /cocoa桥接?
在一个纯粹的C ++世界中,我们可以在编译时间使用基于模板的编译时和运行时技术(例如,大部分自动将marshall传入或传出使用传统types的调用)的组合,在不同的组件或接口之间生成接口或粘合代码。
当需要将Objective-C / Cocoa与GUI,系统集成或IPC接口的C ++应用程序进行交互时,由于input较不严格,事情变得更加困难 – 但是通常不会再需要一个扁平的重复接口层:瘦桥接代表必须定义或转换代码语言桥接调用必须写。
如果您必须处理非平凡大小的接口,并且希望避免基于脚本的代码生成,那么这很快就会变得繁琐,而且每次重构都必须发生,这只是一个痛苦。 使用(模板)元编程和Objective-C运行时库的组合,应该可以大大减less代码量…
在我重新发明轮子(可能浪费时间)之前 ,有没有人知道在这个方向上的技术,最佳实践或例子?
举一个例子,假设我们需要一个支持这个非正式协议的委托:
- (NSString*)concatString:(NSString*)s1 withString:(NSString*)s2; - (NSNumber*) indexOf:(CustomClass*)obj;
而不是实现一个明确桥接到C ++实例的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; } };
用户为了支持其他types应该需要的所有东西都是专门化一个转换模板函数:
template<class To, class From> To convert(const From&); template<> NSString* convert<NSString*, std::string>(const std::string& s) { // ... } // ...
上面的例子当然不会忽略对正式协议的支持等,但是应该明白这一点。 另外,由于Objc运行时types的types信息大部分会衰减到某些本地types或类types,我不认为可以避免为delegate方法显式指定参数和返回types。
我没有发现任何令人满意的结果,并提出了一个原型,根据以下非正式协议:
- (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; }
允许创build和传递一个委托:
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获得 。 build设性的意见和想法的欢迎。
你看了wxWidgets库吗? 我没有在Objective-C中编写代码,但至less开发人员声称对Cocoa / Objective-C的体面支持。 这意味着,他们有一些从C ++实现的映射。 图书馆的网站是http://www.wxwidgets.org 。