Skip to content

Instantly share code, notes, and snippets.

Last active August 16, 2020 08:03
Show Gist options
  • Save ayyybe/cff8f74b98e21444496218ea3607db5d to your computer and use it in GitHub Desktop.
Save ayyybe/cff8f74b98e21444496218ea3607db5d to your computer and use it in GitHub Desktop.
A small Cocoa app written purely in C using the objc runtime (part of a scrapped project)
// compile with
// clang main.c -framework Cocoa
#include <ApplicationServices/ApplicationServices.h>
#include <CoreFoundation/CoreFoundation.h>
#include <CoreGraphics/CoreGraphics.h>
#include <objc/runtime.h>
#include <objc/message.h>
#include <stdio.h>
extern id NSApp;
int RunApplication(void) {
// Create app event loop
((id (*)(Class, SEL)) objc_msgSend)(objc_getClass("NSApplication"), sel_registerName("sharedApplication"));
if (NSApp == NULL) {
fprintf(stderr, "Failed to create NSApplication! Terminating...\n");
return 2;
// yay private APIs
// change process name to "Minecraft 2"
CFBundleRef launchServicesBundle = CFBundleGetBundleWithIdentifier(CFSTR(""));
CFTypeRef asn = ((CFTypeRef (*)()) CFBundleGetFunctionPointerForName(launchServicesBundle, CFSTR("_LSGetCurrentApplicationASN")))();
CFStringRef *displayNameKey = CFBundleGetDataPointerForName(launchServicesBundle, CFSTR("_kLSDisplayNameKey"));
OSStatus setNameResult = ((OSStatus (*)(int, CFTypeRef, CFStringRef, CFStringRef, void*)) CFBundleGetFunctionPointerForName(launchServicesBundle, CFSTR("_LSSetApplicationInformationItem")))(
-2, // yay magic values
CFSTR("Minecraft 2"),
printf("setNameResult: %d\n", setNameResult); // 0 = noErr, for others
// Initialize & close dummy window
id window = class_createInstance(objc_getClass("NSWindow"), 0);
window = ((id (*)(id, SEL, struct CGRect, int, int, BOOL)) objc_msgSend)(window, sel_registerName("initWithContentRect:styleMask:backing:defer:"), (struct CGRect) {0, 0, 0, 0}, 0, 2, false);
((id (*)(id, SEL)) objc_msgSend)(window, sel_registerName("close"));
// Start app event loop (to keep the program running)
((id (*)(id, SEL)) objc_msgSend)(NSApp, sel_registerName("run"));
return 0;
int main(int argc, char *argv[]) {
id pool = class_createInstance(objc_getClass("NSAutoreleasePool"), 0);
pool = ((id (*)(id, SEL)) objc_msgSend)(pool, sel_registerName("init"));
if (pool == NULL) {
fprintf(stderr, "Failed to create NSAutoreleasePool! Terminating...\n");
return 1;
int code = RunApplication();
((id (*)(id, SEL)) objc_msgSend)(pool, sel_registerName("drain"));
return code;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment