Entonces, hoy estaba aburrido y decidí meterme con la interpolación de C++/Obj-C, y encontré la manera de crear una configuración muy interesante.Objective-C - Desventajas de la creación de puentes con C++?
@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();
};
Como puede ver, la interfaz es bastante sencilla y fácil de entender. Creamos dos interfaces (casi) idénticas, una para un objeto C++ y otra para un protocolo Obj-C.
Ahora, he encontrado una manera de implementar esto, pero prepárate, esto se pone feo:
// 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();
}), "[email protected]:");
class_addMethod(NSCPPObj_class, @selector(somethingThatReturnsAValue), imp_implementationWithBlock(^(id self) {
return ((struct NSCPPObj *) self)->somethingThatReturnsAValue();
}), "[email protected]:");
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;
}
voy a resumir lo que esto hace:
- asigna un par de Clase
- Agrega todos los métodos de clase e instancia al objeto
- Registra la clase Pair
Ahora, como se puede ver, esto no es muy flexible, pero funciona, y es un camino de dos vías:
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;
También puede crear el objeto utilizando new NSCPPObj(15)
, pero recuerde que debe ¡bórralo! Obviamente, esto puede funcionar en un entorno ARC o que no sea ARC, pero ARC requiere algunos moldes puente adicionales.
Por lo tanto, llegué a la verdadera pregunta:
¿Cuáles son los pros/contras de esta estructura de diseño? Puedo enumerar algunos fuera de la parte superior de mi cabeza:
Pros:
- sobrecarga de operadores con C++
- método de Enlace dinámico con ObjC
- se puede construir en cualquiera de C++ o la moda ObjC
Contras:
- duro de leer aplicación
- selectores & fijaciones deben ser agregados para cada aplicación C++ añade a la interfaz
- objeto clase no se puede hacer referencia directamente
Así que, después de todo eso, ¿Recomendado estructura de diseño en una aplicación? y por qué.
Sé muy poco de C++ para dar una buena respuesta, pero me pregunto si la respuesta a esto depende de en qué tipo de aplicación estás trabajando exactamente. Un juego existente de C++ que se transfiere puede encontrar esto mucho más útil que una simple aplicación de utilidad ... y un programador de C++ experimentado puede apreciarlo más que alguien que está fuertemente orientado a Objective-C. – lxt
Votación para reabrir. Entiendo que esto puede ser "no constructivo", pero este es un sitio de la comunidad. Reconozco que eres un moderador, pero ya que eres el único que quería que esto se cerrara. –
No soy moderador y marqué esta pregunta para su revisión. Está fuera de tema. – mydogisbox