2009-07-09 14 views
5

Tengo una clase Objective-C que contiene una estructura C-style. Necesito llamar a una función C pasando un puntero a este miembro de objeto (propiedad a.k.a.) Por mi vida, no puedo entender cómo obtener la dirección de esta estructura C. Usando el operador tradicional & para obtener la dirección, obtengo un error del compilador LValue.Obtener la dirección de una propiedad Objective-c (que es una estructura C)

typedef struct _myStruct 
{ 
    int aNumber; 
}MyStruct, *pMyStruct; 

@interface MyClass : NSObject { 
    MyStruct mystruct; 
} 
@property (readwrite) MyStruct myStruct; 
@end 

Los código siguiente produce un error de compilación:

MyClass* myClass = [[MyClass alloc] init]; 

MyStruct* p = &(myClass.myStruct); 

¿Cómo puedo obtener un puntero a la myStruct miembro del objeto myClass?

+0

No sé si esto funcionará, pero pruebe MyStruct * p = (MyStruct *) & (myClass.myStruct.aNumber); –

+0

El operador & toma un lvalor. El resultado de una llamada a un método es un valor r. – Chuck

Respuesta

2

MyStruct mystruct es privado en MyClass, supongo que cuando usted hace myClass.myStruct, usted solo hace referencia al método de acceso generado, no a la estructura real.

No creo que pueda acceder a la variable de instancia (estructura en este caso) desde fuera porque es privada.

+0

Yo también asumo que myClass.myStruct está obteniendo el valor devuelto por el método de acceso, no la estructura real que es lo que quiero. Suponiendo, hago la variable de instancia privada ... ¿cómo puedo obtener un puntero a la estructura real y no al método de acceso? –

+0

Puede intentar devolver la dirección desde un método miembro (vea la respuesta de Chuck) o puede agregar un método a la clase MyClass que llamará a la API C y pasará la dirección de la estructura de mystruct. – stefanB

2

Para obtener un puntero a la variable de instancia myStruct, debe escribir un método que devuelva un puntero a esa variable de instancia.

- (void)getMyStructPointer:(MyStruct **)outStruct { 
    *outstruct = &myStruct; 
} 

No creo que esta sea una buena idea, sin embargo. Otros objetos no deberían estar mutando el ivar de ese objeto debajo de él, y eso es lo único que se puede hacer con un puntero a la estructura que no se puede hacer con una copia de la estructura devuelta por el valor.

+2

A menos que la estructura sea muy grande; el uso de la memoria podría ser un problema. –

+0

tal vez 'setMyStructPointer:'? –

2

La pregunta en sí demuestra una falta de comprensión de al menos la terminología.

una propiedad es una interfaz que consta de dos (o uno de sólo lectura) los métodos hechos públicos por el objeto, a saber, los métodos getter y setter, en este caso:

- (MyStruct) myStruct; 
- (void) setMyStruct: (MyStruct) newMyStruct; 

no tiene sentido hablar de "tomando la dirección de una propiedad".

Puede tomar la dirección de una variable de instancia (ivar). En este caso tiene un ivar llamado mystruct, y puede tomar la dirección del mismo con &mystruct en un método de MyClass. Como está marcado @protected (de forma predeterminada), puede tomar la dirección del mismo en una subclase usando &self->mystruct. Si lo marca @public, puede tomar la dirección usando &myobj->mystruct. Esta es una idea terrible, y realmente deberían reconsiderar esto, pero podrían hacerlo.

Si solo desea la dirección del ivar para un propósito de corta duración (por ejemplo, si MyStruct fuera grande) podría hacerlo, pero sería muy inusual, y sería mejor que escribiera un nombre explícitamente método como:

- (MyStruct*) getAddressForSettingMyStruct; 

y si solo es de solo lectura, sería aún mejor utilizar const MyStruct *.

+12

Esta respuesta es una especie de esnob. Se bueno. – Brenden

2

A menudo hay buenas razones para hacer lo que se pide en la publicación original, dado que las aplicaciones de Objective-C a menudo tienen que trabajar con API C/C++ que toman punteros a estructuras y tipos similares, pero en una aplicación Cocoa ' A menudo deseo almacenar dichos datos en clases Objective-C para la gestión de datos, la recopilación en matrices y diccionarios, etc.

Aunque esta pregunta ha sido por un tiempo no veo la respuesta clara, que es: puede tener un método que devuelva la dirección de los datos que respaldan su propiedad, pero en ese método no use " self "o pasará por el acceso y aún no funcionará.

- (const MyStruct*) getMyStructPtr 
{ 
    return &mystruct; 
} 

Tenga en cuenta que estoy usando la propiedad declarada del Programa Operativo, pero no hace referencia a ella como self.mystruct, lo que generaría un error de compilación (debido a que invoca el método getter sintetizada).

+0

Como un ejemplo concreto de por qué esto es útil: estoy haciendo un poco de trabajo de CoreMIDI y tengo un objeto Objective-C envolviendo la estructura MIDIPacket que me permite almacenarlo en NSArrays y también agregar algunos métodos de conveniencia. Los métodos API marco en C requieren un puntero const para la estructura, por lo que mi clase Object-C tiene un método como el anterior para devolver el puntero al miembro de datos. Para los tipos de estructuras simples, puede ser preferible usar NSValue, pero dado que MIDIPacket es dinámico (puede ser más grande que su tamaño declarado), una clase de contenedor personalizada es el camino a seguir. – orpheist

+0

Gracias, ahora mis subclases finalmente pueden llegar al CGAffineTransform establecido en la clase principal. –

+0

He utilizado su solución en una respuesta a una pregunta relacionada anterior: [Objective-C Address of property expression] (http://stackoverflow.com/questions/27468595/objective-c-address-of-property-expression/ 40247837 # 40247837) –

Cuestiones relacionadas