Skip to content

Instantly share code, notes, and snippets.

@andreyvit
Created May 5, 2012 04:02
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andreyvit/2599564 to your computer and use it in GitHub Desktop.
Save andreyvit/2599564 to your computer and use it in GitHub Desktop.
Fake an Objective-C class out of a C++ class
// Fakes an Objective-C class out of a C++ class.
//
// Note that this is a very bad and completely superfluous idea, but after looking up a way
// to build Objective-C classes at run time, I just had to do this no matter what. (Besides,
// I really hated maintaining mutual pointers in UIElement/UIElementDelegate class pairs.)
//
// Building up a whole class from scratch (objc_allocateClassPair) looked like a lot of trouble,
// so I compile a real Objective-C class instead, but instead of instantiating it by regular means
// (alloc/init or class_createInstance), I simply cast a part of a C++ object to (id).
// I've looked at the source code for class_createInstance and this hack should work perfectly,
// but of course we're relying on a private implementation detail of Objective-C runtime here.
//
// The beauty is that if I inherit from ObjCObject, I can let C++ figure out the pointer arithmetic
// necessary to convert between (SomeUIElement *) and (ObjCObject *, aka id).
//
// Our use case is so trivial that it makes no sense to apply any kind of tricks here. However,
// again, I couldn't help myself, and hey, it's my product, I want to have fun writing it.
class ObjCObject {
public:
Class isa;
// NSObject holds reference counts in a separate hashtable, so we don't need to allocate space for that
ObjCObject(Class isa) {
this->isa = isa;
}
id self() {
return (id)this;
}
template <typename T>
static T *from_id(id obj) {
return static_cast<T *>(reinterpret_cast<ObjCObject *>(obj));
}
private:
// CoreFoundation wants ObjC classes to be at least 16 bytes in length,
void *_cf_filler[3];
};
// usage example:
class WindowUIElement : public UIElement, public ObjCObject { ... };
@interface WindowUIElementDelegate : NSObject <NSWindowDelegate>
@end
WindowUIElement::WindowUIElement(...) : UIElement(...), ObjCObject([WindowUIElementDelegate class]) {
}
void WindowUIElement::some_method() {
[my_window_ setDelegate:self()];
}
@implementation WindowUIElementDelegate
- (void)windowDidBecomeKey:(NSNotification *)notification {
WindowUIElement *that = ObjCObject::from_id<WindowUIElement>(self);
...
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment