Objective-C - 与C ++桥接的缺点? [英] Objective-C - Disadvantages to Bridging With 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;
}
我会总结一下:
- 分配类对
- 将所有类和实例方法添加到对象
- 注册类对
现在,你可以看到,这不是很灵活,但它可以工作, 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:
优点:
- 运算符使用C ++重载
- 使用ObjC的动态方法绑定
- 可以用C ++或ObjC方式构建
缺点:
- 难以阅读的实施
- 选择器&必须为添加到接口的每个C ++实现添加绑定
- 无法直接引用类对象
推荐答案
毕竟,你会在
应用程序中推荐这种设计结构吗?为什么。
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屋!