Skip to content

Instantly share code, notes, and snippets.

@floooh
Created March 7, 2021 17:56
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save floooh/b3cec3649bd38c7f47f4979f81a99f74 to your computer and use it in GitHub Desktop.
Save floooh/b3cec3649bd38c7f47f4979f81a99f74 to your computer and use it in GitHub Desktop.
C-on-ObjC experiments...
// which is then used like this
// (helper functions like oc_alloc() and oc_alloc_init() will move into a header later)
#include <stdio.h>
#include <assert.h>
#include "hello_macos.h"
Class app_delegate_class;
id app_delegate;
id oc_alloc(Class cls) {
return ((id(*)(id,SEL))objc_msgSend)((id)cls, sel_getUid("alloc"));
}
id oc_alloc_init(Class cls) {
return ((id(*)(id,SEL))objc_msgSend)(oc_alloc(cls), sel_getUid("init"));
}
void didFinishLaunching(id obj, SEL sel, NSNotification* notification) {
NSWindow* win = (NSWindow*) oc_alloc(objc_lookUpClass("NSWindow"));
uint64_t style_mask =
NSWindowStyleMaskTitled |
NSWindowStyleMaskClosable |
NSWindowStyleMaskMiniaturizable |
NSWindowStyleMaskResizable;
NSWindow_initWithContentRect_styleMask_backing_defer(
win,
(NSRect){ .origin = { 50, 50 }, .size = { 300, 300 } },
style_mask,
NSBackingStoreBuffered,
false);
NSWindow_makeKeyAndOrderFront(win, 0);
}
void init_delegate(void) {
// create and register a new app-delegate class
app_delegate_class = objc_allocateClassPair(objc_lookUpClass("NSObject"), "HelloAppDelegate", 0);
assert(app_delegate_class);
class_addMethod(app_delegate_class, sel_getUid("applicationDidFinishLaunching:"), (IMP)didFinishLaunching, "v@@");
objc_registerClassPair(app_delegate_class);
app_delegate = oc_alloc_init(app_delegate_class);
printf("app delegate: %p\n", app_delegate);
}
int main() {
init_delegate();
NSApplication* app = NSApplication_sharedApplication();
NSApplication_activateIgnoringOtherApps(app, true);
NSApplication_setActivationPolicy(app, NSApplicationActivationPolicyRegular);
NSApplication_setDelegate(app, (NSApplicationDelegate*)app_delegate);
printf("app: %p\n", app);
NSApplication_run(app);
return 0;
}
// which yields this generated C header...
#include <stdint.h>
#include <objc/objc-runtime.h>
typedef struct NSNotification { } NSNotification;
typedef struct NSApplication { } NSApplication;
typedef struct NSApplicationDelegate { } NSApplicationDelegate;
typedef struct NSWindow { } NSWindow;
typedef enum NSBackingStoreType: uint64_t {
NSBackingStoreRetained = 0,
NSBackingStoreNonretained = 1,
NSBackingStoreBuffered = 2,
} NSBackingStoreType;
typedef enum NSApplicationActivationPolicy: int64_t {
NSApplicationActivationPolicyRegular,
NSApplicationActivationPolicyAccessory,
NSApplicationActivationPolicyProhibited,
} NSApplicationActivationPolicy;
typedef enum NSWindowStyleMask: uint64_t {
NSWindowStyleMaskBorderless = 0,
NSWindowStyleMaskTitled = 1<<0,
NSWindowStyleMaskClosable = 1<<1,
NSWindowStyleMaskMiniaturizable = 1<<2,
NSWindowStyleMaskResizable = 1<<3,
NSWindowStyleMaskTexturedBackground = 1<<8,
NSWindowStyleMaskUnifiedTitleAndToolbar = 1<<12,
NSWindowStyleMaskFullScreen = 1<<14,
NSWindowStyleMaskFullSizeContentView = 1<<15,
NSWindowStyleMaskUtilityWindow = 1<<4,
NSWindowStyleMaskDocModalWindow = 1<<6,
NSWindowStyleMaskNonactivatingPanel = 1<<7,
NSWindowStyleMaskHUDWindow = 1<<13,
} NSWindowStyleMask;
typedef struct CGPoint {
double x;
double y;
} CGPoint;
typedef struct CGSize {
double width;
double height;
} CGSize;
typedef struct NSRect {
CGPoint origin;
CGSize size;
} NSRect;
static void NSApplication_activateIgnoringOtherApps(NSApplication * self, bool flag) {
return ((void(*)(void*,void*,bool))objc_msgSend)((void*)self, (void*)sel_getUid("activateIgnoringOtherApps:"), flag);
}
static void NSApplication_run(NSApplication * self) {
return ((void(*)(void*,void*))objc_msgSend)((void*)self, (void*)sel_getUid("run"));
}
static bool NSApplication_setActivationPolicy(NSApplication * self, NSApplicationActivationPolicy activationPolicy) {
return ((bool(*)(void*,void*,NSApplicationActivationPolicy))objc_msgSend)((void*)self, (void*)sel_getUid("setActivationPolicy:"), activationPolicy);
}
static NSApplication * NSApplication_sharedApplication() {
return ((NSApplication *(*)(void*,void*))objc_msgSend)((void*)objc_getClass("NSApplication"), (void*)sel_getUid("sharedApplication"));
}
static void NSApplication_setDelegate(NSApplication * self, NSApplicationDelegate * delegate) {
return ((void(*)(void*,void*,NSApplicationDelegate *))objc_msgSend)((void*)self, (void*)sel_getUid("setDelegate:"), delegate);
}
static NSWindow* NSWindow_initWithContentRect_styleMask_backing_defer(NSWindow * self, NSRect contentRect, NSWindowStyleMask style, NSBackingStoreType backingStoreType, bool flag) {
return ((NSWindow*(*)(void*,void*,NSRect,NSWindowStyleMask,NSBackingStoreType,bool))objc_msgSend)((void*)self, (void*)sel_getUid("initWithContentRect:styleMask:backing:defer:"), contentRect, style, backingStoreType, flag);
}
static void NSWindow_makeKeyAndOrderFront(NSWindow * self, id sender) {
return ((void(*)(void*,void*,id))objc_msgSend)((void*)self, (void*)sel_getUid("makeKeyAndOrderFront:"), sender);
}
// this describes the macOS types we want to extract
{
"c_prefix": "",
"headers": {
"imports": [ "Cocoa/Cocoa.h" ],
"includes": []
},
"exports": {
"CGPoint": [ ],
"CGSize": [ ],
"NSRect": [ ],
"NSApplicationActivationPolicy": [ ],
"NSNotification": [ ],
"NSApplicationDelegate": [ ],
"NSApplication": [
"sharedApplication",
"setActivationPolicy:",
"activateIgnoringOtherApps:",
"setDelegate:",
"run"
],
"NSWindowStyleMask": [ ],
"NSBackingStoreType": [ ],
"NSWindow": [
"initWithContentRect:styleMask:backing:defer:",
"makeKeyAndOrderFront:"
]
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment