代码之家  ›  专栏  ›  技术社区  ›  Georg Fritzsche

通过元编程减轻C++到Objul-C/COCOA桥接?

  •  34
  • Georg Fritzsche  · 技术社区  · 15 年前

    在纯C++世界中,我们可以使用基于模板的编译时间和运行时技术的组合,在编译时在不同组件或接口之间生成接口或粘贴代码。 (例如,大多数情况下,使用传统类型自动对呼叫/从呼叫进行马歇尔处理) .

    当必须将C++应用程序与ObjuleC/CCOA接口用于GUI、系统集成或IPC时,由于不太严格的类型化,事情变得更加困难,但通常不需要一个平坦的接口层:必须定义瘦桥接委托或转换代码到语言桥接调用。

    如果您必须处理非琐碎大小的接口,并且希望避免基于脚本的代码生成,那么这很快就会变得很麻烦,而且每次重构都会很麻烦。使用(模板)元编程和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运行时类型的类型信息主要衰减到 一些本机类型或类类型 我不认为可以避免为委托方法显式地指定参数和返回类型。

    2 回复  |  直到 15 年前
        1
  •  5
  •   Gelatin    15 年前

    我没有发现任何令人满意的东西,并提出了一个原型,考虑到以下非正式协议:

    - (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;
    }
    

    允许创建和传递委托:

    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函数 也可以传递对象,这意味着 Boost绑定 也可以很容易地使用。

    虽然基本想法可行,但这仍然是一个原型。我做了一个简短的 blog post 主题和原型源可用 via bitbucket . 欢迎有建设性的意见和想法。

        2
  •  4
  •   Kerido    15 年前

    你看过wxwidgets库吗?我不在ObjuleC中进行编码,但至少开发人员声称对COCOA/Objtovi-C的支持是正确的,这意味着它们从某种程度上实现了C++的映射。图书馆的网站是 http://www.wxwidgets.org .