Get the address of an Objective-c property (which is a C struct)
Asked Answered
I

4

7

I have an Objective-C class which contains a C-style struct. I need to call a C function passing a pointer to this object member (a.k.a. property). For the life of me, I can't figure out how to get the address of this C struct. Using the traditional & operator to get the address, I'm getting an LValue compiler error.

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

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

The following code results in a compiler error:

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

MyStruct* p = &(myClass.myStruct);

How do I get a pointer to the myStruct member of the myClass object?

Icebreaker answered 9/7, 2009 at 5:43 Comment(2)
I don't know if this will work, but try MyStruct* p = (MyStruct*)&(myClass.myStruct.aNumber);Teak
The & operator takes an lvalue. The result of a method call is an rvalue.Haddington
B
4

There are often pretty good reasons to do what the original post is asking, given that Objective-C apps often have to work with C/C++ API's that take pointers to structs and similar types, but in a Cocoa app you'll often want to store such data in Objective-C classes for data management, collection in arrays and dictionaries, etc.

Though this question has been up for awhile I don't see the clear answer, which is: you can have a method that returns the address of the data that's backing your property, but in that method don't use "self" or it will go through the accessor and still not work.

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

Note that I'm using the declared property from the OP, but not referencing it as self.mystruct, which would generate a compiler error (because that invokes the synthesized getter method).

Brest answered 10/6, 2015 at 9:9 Comment(3)
As a concrete example why this is useful - I'm doing some CoreMIDI work and have an Objective-C object wrapping the MIDIPacket struct which lets me store it in NSArrays and also add some convenience methods. The framework API methods in C require a const pointer to the struct, so my objective-C class has a method like above to return the pointer to the data member. For simple struct types it may be preferable to just use NSValue, but because MIDIPacket is dynamic (it may be larger than its declared size) a custom wrapper class is the way to go.Brest
Thank you, now my subclasses can finally get at the CGAffineTransform set in the parent class.Smokeproof
I've used your solution in an answer to an old related question: Objective-C Address of property expressionSmokeproof
A
2

MyStruct mystruct is private in MyClass, I assume when you do myClass.myStruct you are only refering to generated accessor method not the actual structure.

I don't think you can access the instance variable (structure in this case) from outside because it is private.

Armillas answered 9/7, 2009 at 6:12 Comment(2)
I too am assuming that myClass.myStruct is getting the value returned by the accessor method - not the actual structure which is what I want. Assuming, I make the instance variable private... how can I get a pointer to the actual structure and not the accessor method?Icebreaker
You can try to return the address from a member method (see Chuck's answer) or you could add method to MyClass class that will call the C api and pass the address of the mystruct structure.Armillas
H
2

To get a pointer to the myStruct instance variable, you need to write a method that returns a pointer to that instance variable.

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

I don't really think this is a good idea, though. Other objects should not be mutating that object's ivar out from under it, and that's the only thing you can do with a pointer to the struct that you can't do with a copy of the struct returned by value.

Haddington answered 9/7, 2009 at 6:24 Comment(2)
Unless the struct is very large; memory usage could potentially be an issue.Gray
maybe setMyStructPointer:?Frication
O
2

The question itself demostrates a lack of understanding of at least the terminology.

A property is an interface consisting of two (or one for readonly) methods made public by the object, namely the getter and setter methods, in this case:

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

It makes no sense to talk about "taking the address of a property".

You can take the address of an instance variable (ivar). In this case you have an ivar named mystruct, and you can take the address of it with &mystruct in a method of MyClass. Since it is marked @protected (by default), you can take the address of it in a subclass using &self->mystruct. If you mark it @public, then you could take the address of it using &myobj->mystruct. This is a terrible idea, and you should really really rethink this, but you could do it.

If you just want the address of the ivar for some short lived purpose (for example, if MyStruct was large) you could do this, but it would be very unusual, and you'd be better off writing an explicitly named method like:

- (MyStruct*) getAddressForSettingMyStruct;

and if it is just read only, even better would be to use const MyStruct*.

Ohm answered 9/7, 2009 at 12:56 Comment(1)
This answer comes off kind of snobbish. Be Nice.Impresa

© 2022 - 2024 — McMap. All rights reserved.