views:

122

answers:

0

Can I, in the GNU Objective-C runtime, attach semi-arbitrary pieces of data to instance variables?

Challenge:

I'm currently working on a kind of Cocoa workalike for Linux, as a sort of pet project. (Please, let's not get sidetracked by all the "use GNUStep" stuff. I know about it, but it doesn't suit my needs. Moving on…) For this purpose I'm trying to cobble together a simple ORM system, reminiscent of DBIx::Class for Perl. The general idea is to make the declaration as simple (read: short) as possible, and if at all possible, without the need to provide +(id)constantClassAttribute methods for overriding.

The general idea is to declare my result classes as follows:

@interface SomeTable : ORMResult {
  unsigned long long id;
  ORMResult *toOneRelation;
  ORMResultSet *toManyRelation;
}

@end

So far, so hoopy. I can now access these fields using [ORMResult self]->ivars, and do all manner of nasty stuff, like automagically generating accessors like -[toManyRelation] or -[setToOneRelation]. Piece of cake. Unfortunately, there are two pieces of information I cannot add using this setup; one is simple enough to solve, the other not so much:

  1. What is the actual result class?

    This is solved by subclassing ORMResult (like SomeTable), and plugging that in there, using runtime dynam(ag)ics to figure out it's to-ness (toMany, toOne).

  2. (And this is the tricky one!) Is the relationship nullable?

    This is less easily solved. My initial ideas were

    1. (ab)using protocols, like so:

      @interface SomeTable : ORMResult {
        unsigned long long id;
        ORMResult <ORMNullable> *toOneRelation;
      }
      
      
      @end
      

      This compiles, but unfortunately, when I try to use GDB to inspect the ivars->ivar_list entries I find that the protocol information isn't actually kept for the runtime to toy with. This makes, I suppose, some kind of twisted sense, as protocol declarations are mostly for the compiler.

    2. Abusing the protocol identifiers (byref, bycopy and friends, using defines:

      @interface SomeTable : ORMResult {
        unsigned long long id;
        nullable OMRResult *toOneRelation;
      }
      
      
      @end
      

      This has the rather obvious drawback of not actually working, as these specifiers apparently only work in protocol method declarations.

The question, then, is how can this attachment of information to the ivars be pulled off in practice?

Note: As mentioned initially, I'm using the GNU Objective-C runtime, as supplied by GCC on Linux; and not the one supplied by Apple!

Edit: Starpox! I forgot a central point: An alternative, of course, is to simply make all relations nullable. This I don't really want, but if no other alternative exists, I guess that's the path I'll end up going down.