2

I am designing automatically persistent objects, and for that I need (a) to locate members which are pointers, (b) to find their locations. The compiler has this information, and I expected that the reflection would provide it, but I cannot figure out how to do it. For example, if an object starts at address 505060

@interface MyClass : NSObject {

  NSString *name; // class offset 4B,  member address 505064
  int code;
  MyClass *next;  // class offset 12B, member address 505072
}
@end
Jasarien
  • 58,279
  • 31
  • 157
  • 188
  • typo: member addresses should be 505064 and 505072 – Jiri Soukup Nov 26 '12 at 15:19
  • just for curiosity: what do u need this information for? – vikingosegundo Nov 26 '12 at 15:19
  • 1
    What about the members of the superclass? – trojanfoe Nov 26 '12 at 15:20
  • Re-inventing persistency is an interesting pursuit, but it would be exceptionally rare that there is any need to do so for any reason beyond academics. – bbum Nov 26 '12 at 19:06
  • (1) For every class, I generate a mask which is like a zero-filled instance with pointer locations (typically 4B) marked by one. Right now,this is done by providing a simple method listing all kinds of – Jiri Soukup Jan 12 '13 at 05:56
  • I am writing a book on serialization and persistent objects. This is a new hot topic, and goes far beyond archiving which requires lot of manual interaction. For example, I can allocate all objects from pages of memory, and save them in one shot without looking at individual objects. When reading the data from disk, I only convert – Jiri Soukup Jan 12 '13 at 06:15
  • ... continue: pointers which I can identify from the mask. This method is similar to what ObjectStore is using for their persitent data and OO databases. – Jiri Soukup Jan 12 '13 at 06:17
  • You're writing an engineering book about a topic you don't know very well...? – Jonathan Grynspan Jan 12 '13 at 06:44

2 Answers2

6

The location of an ivar relative to its owning object's address is an implementation detail. While it's a well-defined implementation detail, there are very few real-world reasons to know an ivar's offset.

If you really need to know where an ivar is, take a look at the Objective-C runtime functions class_getInstanceVariable() and ivar_getOffset(). However, if you tell us what you're trying to do, we may be able to suggest a smarter approach to solving your problem.

Jonathan Grynspan
  • 43,286
  • 8
  • 74
  • 104
  • This gives me the locations, but I do not know how to detect which variables are pointers. Do you? – Jiri Soukup Jan 12 '13 at 06:20
  • Detecting which ivars are pointers is a different question from the one you originally asked. It also doesn't sound very sane--why do you want to do it? What do you think you will accomplish? – Jonathan Grynspan Jan 12 '13 at 06:43
0

You can easily obtain the address of a field by getting a reference to it:

@interface MyClass : NSObject
{    
  NSString *name; // class offset 4B,  member address 50564
  int code;
  MyClass *next;  // class offset 12B, member address 50572 
} 
@end


void *pointer = &name;

Or you can use directly the ObjectiveC runtime (see Jonhatan answer)

But this is not how persistency should be implemented in ObjectiveC, for this you have NSCoding and such things. Going low level with ObjectiveC instances which have vtables and such is not a good idea. If you really want to implement persistency at a low level I suggest you to use something like a memento pattern to have an internal state which is separated from the implementation and that can be implemented purely in C.

Jack
  • 131,802
  • 30
  • 241
  • 343
  • 1
    Reflection surely does exist in Objective-C. It's just not used very often. – Jonathan Grynspan Nov 26 '12 at 15:22
  • It does, but not for addresses of fields. Of course it does exist, otherwise you wouldn't be able to catch __no such selector__ errors. Address of fields are a lower level compared to ObjectiveC itself, so that's true even for reflection. – Jack Nov 26 '12 at 15:23
  • Sure it does. `ivar_getOffset()`. – Jonathan Grynspan Nov 26 '12 at 15:23
  • That's not ObjectiveC, that's C indeed. – Jack Nov 26 '12 at 15:24
  • Reflection does exist. Objective C has a runtime because it is C with Scala(?). Hence why this doesn't fail: `[nil nil];`. There is a runtime. A runtime = reflection. – Cole Tobin Nov 26 '12 at 15:26
  • Please read my answer: I've never said reflection doesn't exist. I said that it doesn't exist directly in ObjectiveC to let you know the address of a field, that's why you go with the ObjectiveC runtime itself (ivar_getOffset()) or directly in C. – Jack Nov 26 '12 at 15:27
  • `ivar_getOffset()` is part of the Objective-C runtime, which is exposed as a set of C functions. This is still part of Objective-C, which comprises both a syntax and a runtime library. C is Objective-C; the latter is a superset of the former, so all valid C is valid Objective-C. – Jonathan Grynspan Nov 26 '12 at 15:27
  • @Jack: That's not what your answer says. Your answer says "since C is how ObejctiveC implements itself under the hood (a class is just a struct) there is no way to know it in such way" which is incorrect. – Jonathan Grynspan Nov 26 '12 at 15:28
  • @Jack: For one, an Objective-C class is not just a struct; an instance of a class is a struct, but a class itself is a *self-documenting* opaque type that contains the name of the class, the layout of an instance's ivars, its superclass, and so forth. – Jonathan Grynspan Nov 26 '12 at 15:29
  • @Jack: For another, your answer states that it is not possible at runtime to perform reflection, which is as previously stated incorrect. Finally, while you're absolutely correct that `NSCoding` is the correct way to do object persistence, the rest of your answer is still wrong and should be corrected. – Jonathan Grynspan Nov 26 '12 at 15:31
  • @JonathanGrynspan: I'm speaking about reflection __to know the address of a field by using ObjectiveC directly__, I think it is quite clear. – Jack Nov 26 '12 at 15:33
  • @Jack: To whit: `ivar_getOffset()`. – Jonathan Grynspan Nov 26 '12 at 15:33
  • @JonathanGrynspan: That's not ObjectiveC. That's a fuction of ObjectiveC runtime. You are not using a feature of the language for your purpose, you are using a C function that provides an utility. Actually that utility function could even not exist in another ObjectiveC implementation so relying on it could be a good or bad idea. – Jack Nov 26 '12 at 15:35
  • @Jack You are making an artificial distinction that does not exist in Objective-C. *Valid C is valid Objective-C*. Objective-C doesn't solely comprise the message dispatch syntax and `@` keywords; it also covers the features of the underlying C language. – Jonathan Grynspan Nov 26 '12 at 15:39
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/20127/discussion-between-jack-and-jonathan-grynspan) – Jack Nov 26 '12 at 15:41
  • I know that offsets are implementation specific, but with what I am doing, I get an implementation specific mask. I am sorry I did not respond immediately, I was off for a while. As I said above, I need not only offsets, but also which variables are pointers and which only values - that is the key of my question. – Jiri Soukup Jan 12 '13 at 06:28