Skip to content

Instantly share code, notes, and snippets.

@TooTallNate
Created July 9, 2011 04:05
Show Gist options
  • Select an option

  • Save TooTallNate/1073294 to your computer and use it in GitHub Desktop.

Select an option

Save TooTallNate/1073294 to your computer and use it in GitHub Desktop.
low-level objc runtime apis
*
!*.m
!Makefile
// To compile: gcc -o array array.m -lobjc -framework Foundation
#include <objc/runtime.h>
#include <dlfcn.h>
#include <stdio.h>
int main() {
void *sdl_library = dlopen("/System/Library/Frameworks/Foundation.framework/Versions/Current/Foundation", RTLD_LAZY);
if (sdl_library == NULL) {
printf("Got dlopen error!\n");
} else {
printf("dlopen successful!\n");
// Set up an NSAutoreleasePool
Class nsautoreleasepool = objc_getClass("NSAutoreleasePool");
id pool = class_createInstance(nsautoreleasepool, 0);
SEL initSel = sel_registerName("init");
id poolAfterInit = objc_msgSend(pool, initSel);
// Create an NSMutableArray
Class nsmutablearray = objc_getClass("NSMutableArray");
// Regular way to create an NSMutableArray,
// equivalent to [[NSMutableArray alloc] initWithCapacity: 10]
id array = objc_msgSend(nsmutablearray, sel_registerName("alloc"));
id arrayAfterInit = objc_msgSend(array, sel_registerName("initWithCapacity:"), 10);
// Alternative, shorthand way of creating an NSMutableArray,
// equivalent to [NSMutableArray arrayWithCapacity: 10]
//id arrayAfterInit = objc_msgSend(nsmutablearray, sel_registerName("arrayWithCapacity:"), 10);
// Add an NSString and the nsma class reference to the array
objc_msgSend(arrayAfterInit, sel_registerName("addObject:"), @"test");
objc_msgSend(arrayAfterInit, sel_registerName("addObject:"), nsmutablearray);
// Print out the length and debug printout
NSLog(@"%d", objc_msgSend(arrayAfterInit, sel_registerName("count")));
NSLog(@"%@", arrayAfterInit);
}
return 0;
}
// To compile: gcc -o hello hello.m -lobjc
#include <objc/runtime.h>
#include <dlfcn.h>
#include <stdio.h>
int main() {
void *sdl_library = dlopen("/System/Library/Frameworks/Foundation.framework/Versions/Current/Foundation", RTLD_LAZY);
if (sdl_library == NULL) {
printf("Got dlopen error!\n");
} else {
printf("dlopen successful!\n");
// Set up an NSAutoreleasePool
Class nsautoreleasepool = objc_getClass("NSAutoreleasePool");
id pool = class_createInstance(nsautoreleasepool, 0);
SEL initSel = sel_registerName("init");
id poolAfterInit = objc_msgSend(pool, initSel);
// Set up a NSString with the contents "Hello World" from a C string
Class nsstring = objc_getClass("NSString");
SEL stringUTF8sel = sel_registerName("stringWithUTF8String:");
id hello = objc_msgSend(nsstring, stringUTF8sel, "Hello World\n");
// Print it back out as a C string
printf("%s", (char *)objc_msgSend(hello, sel_registerName("UTF8String")));
}
return 0;
}
CC = gcc
SRC_FILES = $(wildcard *.m)
OUT_FILES = $(SRC_FILES:.m=)
.PHONY: all
all: $(OUT_FILES)
%: %.m
$(CC) -g -lobjc -framework Foundation -o $@ $<
.PHONY: clean
clean:
rm -f $(OUT_FILES)
// To compile: gcc -o scriptingbridge scriptingbridge.m -lobjc -framework Foundation
#import <Foundation/Foundation.h>
#include <objc/runtime.h>
#include <dlfcn.h>
#include <stdio.h>
int main(int argc, char **argv) {
dlopen("/System/Library/Frameworks/Foundation.framework/Versions/Current/Foundation", RTLD_LAZY);
dlopen("/System/Library/Frameworks/ScriptingBridge.framework/Versions/Current/ScriptingBridge", RTLD_LAZY);
// Set up an NSAutoreleasePool
Class nsautoreleasepool = objc_getClass("NSAutoreleasePool");
id pool = class_createInstance(nsautoreleasepool, 0);
SEL initSel = sel_registerName("init");
id poolAfterInit = objc_msgSend(pool, initSel);
// Create an instance of the local iTunes installation
Class sbapplication = objc_getClass("SBApplication");
id itunes = objc_msgSend(sbapplication, sel_registerName("applicationWithBundleIdentifier:"), @"com.apple.iTunes");
// Is iTunes running?
id running = objc_msgSend(itunes, sel_registerName("isRunning"));
NSLog(@"iTunes Running: %d", running);
// Print out the name of the iTunes application
id name = objc_msgSend(itunes, sel_registerName("name"));
NSLog(@"Name: %@", name);
// Print out the current volume
NSInteger curVol = (NSInteger) objc_msgSend(itunes, sel_registerName("soundVolume"));
NSLog(@"Current Volume: %d", curVol);
// If an argument was passed, assume it's an integer and set iTunes' volume
if (argc > 1) {
NSInteger volToSet = atoi(argv[1]);
objc_msgSend(itunes, sel_registerName("setSoundVolume:"), volToSet);
NSLog(@"Set Volume to: %d", volToSet);
}
return 0;
}
@sancarn
Copy link
Copy Markdown

sancarn commented Mar 6, 2023

Realise this was created a long time ago but is a really useful resource.

objc_msgSend appears to have a odd definition where the params are just inserted wherever. Do you know if it's possible to send parameters gradually to an object by repeatedly sending objc_msgSend() (or some other function) for parameters instead?

id itunesPre = objc_msgSend(sbapplication, sel_registerName("applicationWithBundleIdentifier:"));
id itunes = objc_msgSend(itunesPre, @"com.apple.iTunes")

Additionally, do you know how to send a named parameter?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment