在一个纯C++的世界中,我们可以使用基于模板的编译时和运行时技术的组合生成不同组件或接口之间的接口或粘合代码(例如,大部分情况下自动转换使用遗留类型的调用)。但是,当需要将C++应用程序与Objective-C/Cocoa用于GUI、系统集成或IPC进行接口处理时,由于类型不够严格,事情变得更加困难,而通常仅需要一个扁平的重复接口层:必须定义薄的桥接代理或编写语言桥接调用的转换代码。
如果必须处理非平凡大小的接口并希望避免基于脚本的代码生成,则这很快变得麻烦,并且每次重构时都很痛苦。使用(模板)元编程和Objective-C运行时库的组合,应该可以大大减少代码量...在我重新发明轮子之前(可能会浪费时间),有人知道在这方面的技术、最佳实践或示例吗?
至于示例,假设我们需要支持这个非正式协议的代理。
如果必须处理非平凡大小的接口并希望避免基于脚本的代码生成,则这很快变得麻烦,并且每次重构时都很痛苦。使用(模板)元编程和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运行时类型的类型信息大部分被分解成某些本地类型或类类型,我认为不能避免对委托方法的参数和返回类型进行明确规定。