Last active
August 16, 2020 08:03
-
-
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)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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("com.apple.LaunchServices")); | |
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 | |
asn, | |
*displayNameKey, | |
CFSTR("Minecraft 2"), | |
NULL); | |
printf("setNameResult: %d\n", setNameResult); // 0 = noErr, https://www.osstatus.com 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