【发布时间】:2011-01-17 14:58:12
【问题描述】:
在纯 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 的类型信息大多衰减为 some-native-types 或 class-type 我不认为代表的参数和返回类型的显式规范- 方法可以避免。
【问题讨论】:
-
这是一个非常有趣的问题。我做了很多这种包装,虽然我使用了很多模式,但我从来没有真正找到一种元编程方法来简化模式。看看是否有人有会很有趣。 C++ 模板不能用于创建 ObjC 类,并且 C++ 缺乏足够的运行时自省来动态创建 ObjC 类。但是,某种模板语言可能是合适的;甚至可能基于宏。我目前正在为我在 Cocoaphany (robnapier.net) 上的下一篇文章研究这个主题,所以我必须多考虑一下。
-
除非我忽略了某些东西,否则我至少可以使用 Obj-C 运行时修改和扩展 Objective-C 类(尚未研究类注册部分)。利用模板检查要绑定的 C++ 签名等。我在那个方向上没有看到大问题……至少现在还没有,这是我问的原因之一:)
-
在我从事的项目中,我们使用以下方法:XML+外部代码生成器。我不知道这是否适合您,但无论如何......据我了解,这种方法一开始很痛苦,但是您不必每次都“重新发明”解决方案。你使用多少种语言并不重要。是的,在我们的例子中,XML 文件也被生成了:它可以通过 GUI 前端访问(当然你总是可以直接更改 XML)。
-
我不喜欢外部代码生成,仅将其用作最后的手段。有趣的问题是如何使用元编程来尽可能避免对代码生成器的需求。我想当我的私人 Mac 到货时,我将不得不开始测试我的想法。
-
这个问题很有趣+1,希望听到你的实验结果@gf。
标签: c++ objective-c cocoa metaprogramming