Objective-C - 与C ++桥接的缺点? [英] Objective-C - Disadvantages to Bridging With C++?

查看:108
本文介绍了Objective-C - 与C ++桥接的缺点?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以,今天我很无聊,决定搞乱C ++ / Obj-C插值,我找到了一种创建一个非常有趣的设置的方法。

So, I was bored today, and decide to mess with C++/Obj-C interpolation, and I found a way to create a very interesting setup.

@protocol NSCPPObj <NSObject>

-(id) init;
-(id) initWithInt:(int) value;
-(int) somethingThatReturnsAValue;
-(void) doSomething;

@end

class NSCPPObj : objc_object {
public:    
    static Class cls();

    int iVar;

    NSCPPObj();
    NSCPPObj(int);

    int somethingThatReturnsAValue();
    void doSomething();
};

如您所见,界面非常简单,易于理解。我们创建两个(几乎)相同的接口,一个用于C ++对象,另一个用于Obj-C协议。

As you can see, the interface is quite straightforward, and easy to understand. We create two (almost) identical interfaces, one for a C++ object, and another for a Obj-C protocol.

现在,我找到了一种实现方法这会变得丑陋:

Now, I found a way to implement this, but brace yourself, this gets ugly:

// NSCPPObj.mm
#import <objc/runtime.h>
#import <iostream>

#import "NSCPPObject.h"

Class NSCPPObj_class = nil;

__attribute__((constructor))
static void initialize()
{
    NSCPPObj_class = objc_allocateClassPair([NSObject class], "NSCPPObj", 0);

    class_addMethod(NSCPPObj_class->isa, @selector(alloc), imp_implementationWithBlock(^(id self) {
        return class_createInstance(NSCPPObj_class, sizeof(struct NSCPPObj));
    }), "@@:");

    class_addMethod(NSCPPObj_class, @selector(init), imp_implementationWithBlock(^(id self) {
        return self;        
    }), "@@:");

    class_addMethod(NSCPPObj_class, @selector(initWithInt:), imp_implementationWithBlock(^(id self, int value) {
        ((struct NSCPPObj *) self)->iVar = value;

        return self;
    }), "@@:i");

    class_addMethod(NSCPPObj_class, @selector(doSomething), imp_implementationWithBlock(^(id self) {
        ((struct NSCPPObj *) self)->doSomething();
    }), "v@:");
    class_addMethod(NSCPPObj_class, @selector(somethingThatReturnsAValue), imp_implementationWithBlock(^(id self) {
        return ((struct NSCPPObj *) self)->somethingThatReturnsAValue();
    }), "i@:");

    objc_registerClassPair(NSCPPObj_class);
}

Class NSCPPObj::cls()
{
    return NSCPPObj_class;
}

NSCPPObj::NSCPPObj()
{
    this->isa = NSCPPObj_class;
    [((id<NSCPPObj>) this) init];
}

NSCPPObj::NSCPPObj(int value)
{
    this->isa = NSCPPObj_class;
    [((id<NSCPPObj>) this) initWithInt:value];
}

void NSCPPObj::doSomething()
{
    std::cout << "Value Is: " << [((id<NSCPPObj>) this) somethingThatReturnsAValue] << std::endl;
}

int NSCPPObj::somethingThatReturnsAValue()
{
    return iVar;
}

我会总结一下:


  1. 分配类对

  2. 将所有类和实例方法添加到对象

  3. 注册类对

现在,你可以看到,这不是很灵活,但它可以工作, way street:

Now, as you can see, this isn't very flexible, but it does work, and it's a two-way street:

id<NSCPPObj> obj = [[NSCPPObj::cls() alloc] initWithInt:15];
[obj doSomething];

NSLog(@"%i", [obj somethingThatReturnsAValue]);
NSLog(@"%@", obj);

NSCPPObj *objAsCPP = (__bridge NSCPPObj *) obj;

objAsCPP->doSomething();
std::cout << objAsCPP->somethingThatReturnsAValue() << std::endl;

您也可以使用 new NSCPPObj(15),但记得删除它!
显然,这可以在ARC或非ARC环境中工作,但ARC需要一些额外的桥接转换。

You can also create the object by using new NSCPPObj(15), but remember to delete it! Obviously, this can work in a ARC or non-ARC environment, but ARC requires a few extra bridged casts.

所以,我来到真正的问题:

此设计结构的优点/缺点是什么?我可以列出我头脑中的几个:

So, I come to the real question:
What are the pros/cons of this design structure? I can list a few off of the top of my head:

优点:


  1. 运算符使用C ++重载

  2. 使用ObjC的动态方法绑定

  3. 可以用C ++或ObjC方式构建

缺点:


  1. 难以阅读的实施

  2. 选择器&必须为添加到接口的每个C ++实现添加绑定

  3. 无法直接引用类对象

推荐答案


毕竟,你会在
应用程序中推荐这种设计结构吗?为什么。

So, after all that, would you recommend this design structure in an application? and why.

否。

码;我特别喜欢使用imp_implementationWithBlock()(但我承认我可能偏偏运行时的特定功能)。当然,像这样的探索总是一个非常有价值的学习工具。

It is a really nice bit of code; I particularly like the use of imp_implementationWithBlock() (but I admit I might be partial to that particular feature of the runtime ;). And, of course, explorations like this are always an incredibly valuable learning tool.

这个问题,在真实世界付款项目使用的上下文中,有效地创建一个相对通用的桥接器,然后必须在任一端具有特定的桥接器以与典型的C ++库或典型的Objective-C API /库接口。换句话说,你已经有效地创建了一个新的运行时派生自两个现有运行时的合并。

The issue, in the context of "real world paying project" use, is that you are effectively creating a relatively generic bridge that will then have to have specific bridges at either end to interface with either typical C++ libraries or typical Objective-C APIs/libraries. To put it another way, you have effectively created a new runtime derived from an amalgamation of two existing runtimes.

而且,正如你在缺点指出,你几乎必须在每个要引入此模式的C ++类之上触摸,换行,修改和/或调试垫片。

And, as you point out in the Cons, you pretty much have to touch, wrap, modify and/or debug a shim on top of every C++ class you want to bring into this pattern.

使用相当多的目标-C ++代码在过去20多年,这样的桥梁一般比它的价值更麻烦。你可能会更好 - 花更少的时间编写和调试代码 - 创建围绕C ++(或C,坦率地)API的简单的Objective-C包装器,然后可以与目标系统的Objective-C框架集成和使用。

In working with quite a bit of Objective-C++ code over the last 20+ years, a bridge like this is generally more trouble than it is worth. You would likely be better off -- spend less time writing and debugging code -- creating simple Objective-C wrappers around the C++ (or C, frankly) APIs that can then be integrated with and consumed by the targeted system's Objective-C frameworks.

这篇关于Objective-C - 与C ++桥接的缺点?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆