Skip to content

Instantly share code, notes, and snippets.

@fjolnir
Created April 30, 2014 08:15
Show Gist options
  • Save fjolnir/347f9860683edfe749a7 to your computer and use it in GitHub Desktop.
Save fjolnir/347f9860683edfe749a7 to your computer and use it in GitHub Desktop.
#![feature(macro_rules)]
extern crate libc;
extern crate sync;
use std::cast::transmute;
use std::c_str::CString;
use std::sync::atomics::{ AtomicUint, INIT_ATOMIC_UINT, SeqCst };
type Sel = uint;
enum ObjcObject {}
type Class<'a> = &'a ObjcObject;
type Id<'a> = &'a ObjcObject;
type NSObjectClass<'a> = Class<'a>;
type NSObject<'a> = Id<'a>;
type NSMutableArrayClass<'a> = NSObjectClass<'a>;
type NSMutableArray<'a> = NSObject<'a>;
type NSStringClass<'a> = NSObjectClass<'a>;
type NSString<'a> = NSObject<'a>;
#[link(name = "Foundation", kind = "framework")]
extern "C" {
fn sel_registerName(sel: *libc::c_char) -> Sel;
fn objc_msgSend(object: Id, sel: Sel, ...) -> Id;
#[link_name="OBJC_CLASS_$_NSMutableArray"]
static NSMutableArrayKlass:ObjcObject;
// #[link_name="OBJC_CLASS_$_NSString"]
// static NSStringKlass:ObjcObject;
}
trait ObjcSelector {
fn as_selector(self) -> Sel;
}
impl ObjcSelector for Sel {
fn as_selector(self) -> Sel { self }
}
impl<'a> ObjcSelector for &'a str {
#[inline]
fn as_selector(self) -> Sel {
unsafe {
self.with_c_str(|cstr| sel_registerName(cstr) )
}
}
}
#[inline]
fn cache_sel(container:&'static AtomicUint, name:&str) -> Sel
{
let mut sel:Sel = container.load(SeqCst);
if sel == 0 {
container.store(name.as_selector(), SeqCst);
sel = container.load(SeqCst);
}
sel
}
trait NSObjectClassInterface {
unsafe fn alloc(self) -> Id;
unsafe fn new(self) -> Id;
}
impl <'a>NSObjectClassInterface for NSObjectClass<'a> {
unsafe fn alloc(self) -> Id {
static mut sel:AtomicUint = INIT_ATOMIC_UINT;
objc_msgSend(self, cache_sel(&sel, "alloc"))
}
unsafe fn new(self) -> Id {
static mut sel:AtomicUint = INIT_ATOMIC_UINT;
objc_msgSend(self, cache_sel(&sel, "new"))
}
}
trait NSObjectInterface {
unsafe fn init(self) -> Id;
unsafe fn description(self) -> NSString;
}
impl <'a>NSObjectInterface for NSObjectClass<'a> {
unsafe fn init(self) -> Id {
static mut sel:AtomicUint = INIT_ATOMIC_UINT;
objc_msgSend(self, cache_sel(&sel, "init"))
}
unsafe fn description(self) -> NSString {
static mut sel:AtomicUint = INIT_ATOMIC_UINT;
objc_msgSend(self, cache_sel(&sel, "description"))
}
}
trait NSStringInterface {
unsafe fn UTF8String(self) -> *u8;
}
impl <'a>NSStringInterface for NSStringClass<'a> {
unsafe fn UTF8String(self) -> *u8 {
static mut sel:AtomicUint = INIT_ATOMIC_UINT;
let imp: extern "C" fn(Id, Sel, ...) -> *u8 = std::cast::transmute(objc_msgSend);
imp(self, cache_sel(&sel, "UTF8String"))
}
}
fn main() {
let arr:NSMutableArrayClass = &NSMutableArrayKlass;
println!("{}", arr as *_ as uint);
unsafe {
let inst = arr.alloc().init();
let inst2 = arr.new();
println!("{}", inst as *_ as uint);
println!("{}", inst2 as *_ as uint);
let buf = arr.description().UTF8String();
println!("{} '{}''", buf, CString::new(buf as *i8, false).as_str());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment