Note that there are some explanatory texts on larger screens.

plurals
  1. POObjective-C - Disadvantages to Bridging With C++?
    text
    copied!<p>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.</p> <pre><code>@protocol NSCPPObj &lt;NSObject&gt; -(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(); }; </code></pre> <p>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.</p> <p>Now, I found a way to implement this, but brace yourself, this gets ugly:</p> <pre><code>// NSCPPObj.mm #import &lt;objc/runtime.h&gt; #import &lt;iostream&gt; #import "NSCPPObject.h" Class NSCPPObj_class = nil; __attribute__((constructor)) static void initialize() { NSCPPObj_class = objc_allocateClassPair([NSObject class], "NSCPPObj", 0); class_addMethod(NSCPPObj_class-&gt;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)-&gt;iVar = value; return self; }), "@@:i"); class_addMethod(NSCPPObj_class, @selector(doSomething), imp_implementationWithBlock(^(id self) { ((struct NSCPPObj *) self)-&gt;doSomething(); }), "v@:"); class_addMethod(NSCPPObj_class, @selector(somethingThatReturnsAValue), imp_implementationWithBlock(^(id self) { return ((struct NSCPPObj *) self)-&gt;somethingThatReturnsAValue(); }), "i@:"); objc_registerClassPair(NSCPPObj_class); } Class NSCPPObj::cls() { return NSCPPObj_class; } NSCPPObj::NSCPPObj() { this-&gt;isa = NSCPPObj_class; [((id&lt;NSCPPObj&gt;) this) init]; } NSCPPObj::NSCPPObj(int value) { this-&gt;isa = NSCPPObj_class; [((id&lt;NSCPPObj&gt;) this) initWithInt:value]; } void NSCPPObj::doSomething() { std::cout &lt;&lt; "Value Is: " &lt;&lt; [((id&lt;NSCPPObj&gt;) this) somethingThatReturnsAValue] &lt;&lt; std::endl; } int NSCPPObj::somethingThatReturnsAValue() { return iVar; } </code></pre> <p>I'll summarize what this does: </p> <ol> <li>Allocates a Class Pair</li> <li>Adds all class and instance methods to the object</li> <li>Registers the class Pair</li> </ol> <p>Now, as you can see, this isn't very flexible, but it does work, and it's a two-way street:</p> <pre><code>id&lt;NSCPPObj&gt; obj = [[NSCPPObj::cls() alloc] initWithInt:15]; [obj doSomething]; NSLog(@"%i", [obj somethingThatReturnsAValue]); NSLog(@"%@", obj); NSCPPObj *objAsCPP = (__bridge NSCPPObj *) obj; objAsCPP-&gt;doSomething(); std::cout &lt;&lt; objAsCPP-&gt;somethingThatReturnsAValue() &lt;&lt; std::endl; </code></pre> <p>You can also create the object by using <code>new NSCPPObj(15)</code>, but remember to delete it! Obviously, this can work in a ARC or non-ARC environment, but ARC requires a few extra bridged casts.</p> <p>So, I come to the real question:<br> What are the pros/cons of this design structure? I can list a few off of the top of my head:</p> <p>Pros:</p> <ol> <li>Operator Overloading with C++</li> <li>Dynamic method binding with ObjC</li> <li>Can be constructed in either a C++ or ObjC fashion</li> </ol> <p>Cons:</p> <ol> <li>Hard-to-read implementation</li> <li>Selectors &amp; bindings must be added for every C++ implementation added to the interface</li> <li>Class object cannot be referenced directly</li> </ol> <p>So, after all that, <em>would you recommend this design structure in an application?</em> and why.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload