So here's the rough structure:
- qix.c defines draw_qix(), etc.
- deco.c defines draw_deco(), etc.
- XScreenSaverView.m defines a subclass of ScreenSaverView that invokes the appropriate draw_ routine.
- Qix.saver is built from qix.o and XScreenSaverView.o.
- Deco.saver is built from deco.o and XScreenSaverView.o.
Now, step 3 up there is the tricky bit. How do I find the appropriate draw routine?
My first attempt was, through the magic of macros, to have both qix.o and attraction.o define the same global variable, xscreensaver_function_table. That works when the screen saver activates for real, but doesn't work when switching savers in System Preferences: what happens is, the first bundle loaded wins. So if Qix is the selected saver, and you switch to Deco, you still get Qix's version of xscreensaver_function_table, and Deco doesn't run.
So then I thought, well, if the code in XScreenSaverView.m knew the name of the saver it was defining, then I could have it look up the symbol by name: it could look for qix_function_table or deco_function_table as appropriate, and both could co-exist in the same address space. CFBundleGetDataPointerForName() seems to be made for this: given a bundle and a string, it gives you the address of the variable of that name.
So, I have two instances of XScreenSaverView, and I want to know which bundle they were instantiated from. [NSBundle bundleForClass:[self class]] tells me which bundle defined the class, which is the first one loaded (and both instances get the same answer, and malfunction in the same familiar way).
The only idea I have at this point is to define a custom subclass of XScreenSaverView for each saver, that looked like:
- @interface XScreenSaverQixView : XScreenSaverView {}
@end
@implementation XScreenSaverQixView
- (NSString *) whoami { return @"Qix"; }
// ...or, more directly:
- (struct table *) table { return qix_function_table; }
@end
But that's annoying because it means auto-generating 200+ source files, which just kind of rubs me the wrong way.
Any other suggestions?