在纯 C++ 世界中,我们可以结合使用基于模板的编译时和运行时技术,在编译时生成不同组件或接口之间的接口或粘合代码(例如,大多数情况下自动编组到使用旧类型的调用/从调用中编组).
然而,当必须将 C++ 应用程序与 Objective-C/Cocoa 接口以实现 GUI、系统集成或 IPC 时,由于类型不太严格,事情变得更加困难 - 但通常只需要一个平面重复接口层:必须使用薄桥接委托必须编写语言桥接调用的定义代码或转换代码。
如果您必须处理规模不小的接口,并且想要避免基于脚本的代码生成,那么这很快就会变得很麻烦,并且每次必须进行重构时都会很痛苦。使用(模板)元编程和 Objective-C 运行时库的组合,应该可以大大减少代码量......
在我重新发明轮子之前(并且可能浪费时间),有人知道这个方向的技术、最佳实践或例子吗?
举个例子,假设我们需要一个支持这个非正式协议的委托:
- (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;
}
};
用户支持其他类型所需要做的就是专门化转换模板函数:
template<class To, class From> To convert(const From&);
template<>
NSString* convert<NSString*, std::string>(const std::string& s) {
// ...
}
// ...
上面的例子当然忽略了对正式协议等的支持,但应该能够表达要点。此外,由于 Objc-runtime-types 的类型信息大部分衰减为某些本机类型或类类型我认为无法避免委托方法的参数和返回类型的显式规范。