Skip to content

Instantly share code, notes, and snippets.

@seanjensengrey
Forked from fjolnir/tlc.lua
Created March 28, 2012 16:04
Show Gist options
  • Save seanjensengrey/2227773 to your computer and use it in GitHub Desktop.
Save seanjensengrey/2227773 to your computer and use it in GitHub Desktop.

Revisions

  1. @fjolnir fjolnir revised this gist Mar 28, 2012. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions tlc.lua
    Original file line number Diff line number Diff line change
    @@ -359,6 +359,7 @@ ffi.metatype("struct objc_class", {
    return ret
    end
    end,
    -- Grafts a lua function onto the class as an instance method, it will only be callable from lua though
    __newindex = function(self,selStr,lambda)
    selStr = selStr:gsub("_", ":")
    local className = class_getName(ffi.cast("Class", self))
  2. @fjolnir fjolnir revised this gist Mar 28, 2012. 1 changed file with 0 additions and 1 deletion.
    1 change: 0 additions & 1 deletion tlc.lua
    Original file line number Diff line number Diff line change
    @@ -57,7 +57,6 @@ else
    typedef int NSInteger;
    typedef unsigned int NSUInteger;
    ]])

    end

    ffi.cdef([[
  3. @fjolnir fjolnir revised this gist Mar 28, 2012. 1 changed file with 11 additions and 5 deletions.
    16 changes: 11 additions & 5 deletions tlc.lua
    Original file line number Diff line number Diff line change
    @@ -46,9 +46,18 @@ local function objc_log(...)
    end

    if ffi.abi("64bit") then
    ffi.cdef("typedef double CGFloat;")
    ffi.cdef([[
    typedef double CGFloat;
    typedef long NSInteger;
    typedef unsigned long NSUInteger;
    ]])
    else
    ffi.cdef("typedef float CGFloat;")
    ffi.cdef([[
    typedef float CGFloat;
    typedef int NSInteger;
    typedef unsigned int NSUInteger;
    ]])

    end

    ffi.cdef([[
    @@ -112,9 +121,6 @@ typedef struct CGPoint { CGFloat x; CGFloat y; } CGPoint;
    typedef struct CGSize { CGFloat width; CGFloat height; } CGSize;
    typedef struct CGRect { CGPoint origin; CGSize size; } CGRect;
    typedef struct CGAffineTransform { CGFloat a; CGFloat b; CGFloat c; CGFloat d; CGFloat tx; CGFloat ty; } CGAffineTransform;
    typedef long NSInteger;
    typedef unsigned long NSUInteger;
    typedef struct _NSRange { NSUInteger location; NSUInteger length; } NSRange;
    typedef struct _NSZone NSZone;
  4. @fjolnir fjolnir revised this gist Mar 28, 2012. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions tlc.lua
    Original file line number Diff line number Diff line change
    @@ -122,8 +122,10 @@ typedef struct _NSZone NSZone;
    struct _NSStringBuffer;
    struct __CFCharacterSet;
    struct __GSFont;
    struct __CFString;
    struct __CFDictionary;
    struct __CFArray;
    struct __CFAllocator;
    struct _NSModalSession;
    ]])

  5. @fjolnir fjolnir revised this gist Mar 28, 2012. 1 changed file with 4 additions and 1 deletion.
    5 changes: 4 additions & 1 deletion tlc.lua
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,5 @@
    -- TLC - The Tiny Lua Cocoa bridge
    -- Note: Only tested with LuaJIT 2.0 Beta 9 on x86_64 with OS X >=10.7.3 & iPhone 4 with iOS 5
    -- Note: Only tested with LuaJit 2 Beta 9 on x86_64 with OS X >=10.7.3 & iPhone 4 with iOS 5

    -- Copyright (c) 2012, Fjölnir Ásgeirsson

    @@ -122,6 +122,9 @@ typedef struct _NSZone NSZone;
    struct _NSStringBuffer;
    struct __CFCharacterSet;
    struct __GSFont;
    struct __CFDictionary;
    struct __CFArray;
    struct _NSModalSession;
    ]])

    CGPoint = ffi.metatype("CGPoint", {})
  6. @fjolnir fjolnir revised this gist Mar 28, 2012. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion tlc.lua
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,5 @@
    -- TLC - The Tiny Lua Cocoa bridge
    -- Note: Only tested on x86_64 with OS X >=10.7.3 & iPhone 4 with iOS 5
    -- Note: Only tested with LuaJIT 2.0 Beta 9 on x86_64 with OS X >=10.7.3 & iPhone 4 with iOS 5

    -- Copyright (c) 2012, Fjölnir Ásgeirsson

  7. @fjolnir fjolnir revised this gist Mar 28, 2012. 1 changed file with 15 additions and 8 deletions.
    23 changes: 15 additions & 8 deletions tlc.lua
    Original file line number Diff line number Diff line change
    @@ -19,8 +19,8 @@
    -- Loading a class: objc_loadClass("MyClass")
    -- Creating objects: MyClass.new() or MyClass.alloc().init()
    -- Retaining&Releasing objects is handled by the lua garbage collector so you should never need to call retain/release
    -- Calling methods: myInstance:doThis_withThis_andThat_(this, this, that)
    -- Colons in selectors are converted to underscores
    -- Calling methods: myInstance:doThis_withThis_andThat(this, this, that)
    -- Colons in selectors are converted to underscores (last one being optional)
    -- Creating blocks: objc_createBlock(myFunction, returnType, argTypes)
    -- returnType: An encoded type specifying what the block should return (Consult https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html for reference)
    -- argTypes: An array of encoded types specifying the argument types the block expects
    @@ -51,11 +51,6 @@ else
    ffi.cdef("typedef float CGFloat;")
    end

    -- Private structs required to load on iOS
    if ffi.arch == "arm" and ffi.os == "OSX" then
    ffi.cdef("struct __GSFont;")
    end

    ffi.cdef([[
    typedef struct objc_class *Class;
    struct objc_class { Class isa; };
    @@ -123,15 +118,17 @@ typedef unsigned long NSUInteger;
    typedef struct _NSRange { NSUInteger location; NSUInteger length; } NSRange;
    typedef struct _NSZone NSZone;
    // NSString dependencies
    // Opaque dependencies
    struct _NSStringBuffer;
    struct __CFCharacterSet;
    struct __GSFont;
    ]])

    CGPoint = ffi.metatype("CGPoint", {})
    CGSize = ffi.metatype("CGSize", {})
    CGRect = ffi.metatype("CGRect", {})
    CGAffineTransform = ffi.metatype("CGAffineTransform", {})
    NSRange = ffi.metatype("NSRange", {})

    local objc_msgSend = ffi.C.objc_msgSend
    local objc_getClass = ffi.C.objc_getClass
    @@ -316,6 +313,11 @@ ffi.metatype("struct objc_class", {
    __index = function(self,selStr)
    selStr = selStr:gsub("_", ":")
    return function(...)
    local argCount = #{...}
    if argCount > 0 and selStr:sub(-1,-1) ~= ":" then
    for i=1, argCount do selStr = selStr..":" end
    end

    local className = class_getName(ffi.cast("Class", self))
    objc_log("Calling +["..className.." "..selStr.."]")
    local methods = objc_classMethodRegistry[className]
    @@ -361,6 +363,11 @@ ffi.metatype("struct objc_object", {
    __index = function(self,selStr)
    selStr = selStr:gsub("_", ":")
    return function(...)
    local argCount = #{...}
    if argCount > 0 and selStr:sub(-1,-1) ~= ":" then
    for i=1, argCount do selStr = selStr..":" end
    end

    local className = object_getClassName(ffi.cast("id", self))
    objc_log("Calling -["..className.." "..selStr.."]")
    local methods = objc_instanceMethodRegistry[className]
  8. @fjolnir fjolnir revised this gist Mar 28, 2012. 1 changed file with 5 additions and 2 deletions.
    7 changes: 5 additions & 2 deletions tlc.lua
    Original file line number Diff line number Diff line change
    @@ -66,6 +66,8 @@ typedef id (*IMP)(id, SEL, ...);
    typedef signed char BOOL;
    typedef struct objc_method *Method;
    id objc_msgSend(id theReceiver, SEL theSelector, ...);
    Class objc_getClass(const char *name);
    const char *class_getName(Class cls);
    Method class_getClassMethod(Class aClass, SEL aSelector);
    @@ -131,6 +133,7 @@ CGSize = ffi.metatype("CGSize", {})
    CGRect = ffi.metatype("CGRect", {})
    CGAffineTransform = ffi.metatype("CGAffineTransform", {})

    local objc_msgSend = ffi.C.objc_msgSend
    local objc_getClass = ffi.C.objc_getClass
    local objc_getMetaClass = ffi.C.objc_getMetaClass

    @@ -325,7 +328,7 @@ ffi.metatype("struct objc_class", {
    method = _objc_readMethod(methodDesc)
    methods[selStr] = method
    else
    error("Unknown selector "..selStr.."\n"..debug.traceback())
    method = objc_msgSend
    end
    end

    @@ -379,7 +382,7 @@ ffi.metatype("struct objc_object", {
    method = _objc_readMethod(methodDesc)
    methods[selStr] = method
    else
    error("Unknown selector: '"..selStr.."'".."\n"..debug.traceback())
    method = objc_msgSend
    end
    end

  9. @fjolnir fjolnir revised this gist Mar 28, 2012. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion tlc.lua
    Original file line number Diff line number Diff line change
    @@ -18,7 +18,7 @@
    -- Usage:
    -- Loading a class: objc_loadClass("MyClass")
    -- Creating objects: MyClass.new() or MyClass.alloc().init()
    -- Objects returned by init* or new are automatically autoreleased
    -- Retaining&Releasing objects is handled by the lua garbage collector so you should never need to call retain/release
    -- Calling methods: myInstance:doThis_withThis_andThat_(this, this, that)
    -- Colons in selectors are converted to underscores
    -- Creating blocks: objc_createBlock(myFunction, returnType, argTypes)
  10. @fjolnir fjolnir revised this gist Mar 28, 2012. 1 changed file with 2 additions and 4 deletions.
    6 changes: 2 additions & 4 deletions tlc.lua
    Original file line number Diff line number Diff line change
    @@ -53,10 +53,7 @@ end

    -- Private structs required to load on iOS
    if ffi.arch == "arm" and ffi.os == "OSX" then
    ffi.cdef([[
    struct __CFCharacterSet;
    struct __GSFont;
    ]])
    ffi.cdef("struct __GSFont;")
    end

    ffi.cdef([[
    @@ -126,6 +123,7 @@ typedef struct _NSZone NSZone;
    // NSString dependencies
    struct _NSStringBuffer;
    struct __CFCharacterSet;
    ]])

    CGPoint = ffi.metatype("CGPoint", {})
  11. @fjolnir fjolnir revised this gist Mar 28, 2012. 1 changed file with 27 additions and 9 deletions.
    36 changes: 27 additions & 9 deletions tlc.lua
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,5 @@
    -- TLC - The Tiny Lua Cocoa bridge
    -- Note: Only tested on x86_64 & OS X >=10.7.3
    -- Note: Only tested on x86_64 with OS X >=10.7.3 & iPhone 4 with iOS 5

    -- Copyright (c) 2012, Fjölnir Ásgeirsson

    @@ -26,6 +26,10 @@
    -- argTypes: An array of encoded types specifying the argument types the block expects
    -- Both return and argument types default to void if none are passed

    if ffi == nil then
    ffi = require("ffi")
    end

    local objc_debug = false
    local function objc_log(...)
    if objc_debug == true then
    @@ -41,14 +45,24 @@ local function objc_log(...)
    end
    end

    if ffi.abi("64bit") then
    ffi.cdef("typedef double CGFloat;")
    else
    ffi.cdef("typedef float CGFloat;")
    end

    -- Private structs required to load on iOS
    if ffi.arch == "arm" and ffi.os == "OSX" then
    ffi.cdef([[
    struct __CFCharacterSet;
    struct __GSFont;
    ]])
    end

    ffi.cdef([[
    typedef struct objc_class *Class;
    struct objc_class {
    Class isa;
    };
    typedef struct objc_object {
    Class isa;
    } *id;
    struct objc_class { Class isa; };
    typedef struct objc_object { Class isa; } *id;
    typedef struct objc_selector *SEL;
    typedef id (*IMP)(id, SEL, ...);
    @@ -100,7 +114,6 @@ struct __block_literal_1 {
    struct __block_literal_1 *_NSConcreteGlobalBlock;
    // NSObject dependencies
    typedef double CGFloat;
    typedef struct CGPoint { CGFloat x; CGFloat y; } CGPoint;
    typedef struct CGSize { CGFloat width; CGFloat height; } CGSize;
    typedef struct CGRect { CGPoint origin; CGSize size; } CGRect;
    @@ -110,10 +123,15 @@ typedef long NSInteger;
    typedef unsigned long NSUInteger;
    typedef struct _NSRange { NSUInteger location; NSUInteger length; } NSRange;
    typedef struct _NSZone NSZone;
    // NSString dependencies
    struct _NSStringBuffer {};
    struct _NSStringBuffer;
    ]])

    CGPoint = ffi.metatype("CGPoint", {})
    CGSize = ffi.metatype("CGSize", {})
    CGRect = ffi.metatype("CGRect", {})
    CGAffineTransform = ffi.metatype("CGAffineTransform", {})

    local objc_getClass = ffi.C.objc_getClass
    local objc_getMetaClass = ffi.C.objc_getMetaClass
  12. @fjolnir fjolnir revised this gist Mar 28, 2012. 1 changed file with 12 additions and 5 deletions.
    17 changes: 12 additions & 5 deletions tlc.lua
    Original file line number Diff line number Diff line change
    @@ -309,10 +309,14 @@ ffi.metatype("struct objc_class", {
    method = _objc_readMethod(methodDesc)
    methods[selStr] = method
    else
    error("Unknown selector "..selStr)
    error("Unknown selector "..selStr.."\n"..debug.traceback())
    end
    end
    local ret = method(ffi.cast("id", self), SEL(selStr), ...)

    local success, ret = pcall(method, ffi.cast("id", self), SEL(selStr), ...)
    if success == false then
    error(ret.."\n"..debug.traceback())
    end

    if ffi.istype("struct objc_object*", ret) then
    if not (selStr:sub(1,5) == "alloc" or selStr == "new") then
    @@ -346,7 +350,7 @@ ffi.metatype("struct objc_object", {
    objc_loadClass(className)
    methods = objc_instanceMethodRegistry[className]
    if methods == nil then
    error("Could not find class "..className)
    error("Could not find class "..className.."\n"..debug.traceback())
    end
    end

    @@ -359,11 +363,14 @@ ffi.metatype("struct objc_object", {
    method = _objc_readMethod(methodDesc)
    methods[selStr] = method
    else
    error("Unknown selector: '"..selStr.."'")
    error("Unknown selector: '"..selStr.."'".."\n"..debug.traceback())
    end
    end

    local ret = method(self, SEL(selStr), ...)
    local success, ret = pcall(method, ffi.cast("id", self), SEL(selStr), ...)
    if success == false then
    error(ret.."\n"..debug.traceback())
    end

    if ffi.istype("id", ret) then
    -- Retain objects that need to be retained
  13. @fjolnir fjolnir revised this gist Mar 28, 2012. 1 changed file with 16 additions and 17 deletions.
    33 changes: 16 additions & 17 deletions tlc.lua
    Original file line number Diff line number Diff line change
    @@ -248,11 +248,6 @@ local function objc_typeEncodingToCType(aEncoding)
    end

    local function _objc_readMethod(method)
    local ret = {
    method = method,
    argCount = method_getNumberOfArguments(method),
    }

    local imp = method_getImplementation(method);
    -- Typecast the IMP
    local typePtr = ffi.new("char[512]")
    @@ -264,7 +259,7 @@ local function _objc_readMethod(method)
    end
    local impTypeStr = ""..retTypeStr.." (*)("

    local argCount = ret.argCount
    local argCount = method_getNumberOfArguments(method)
    for j=0, argCount-1 do
    method_getArgumentType(method, j, typePtr, 512);
    local typeStr = ffi.string(typePtr)
    @@ -282,9 +277,7 @@ local function _objc_readMethod(method)
    impTypeStr = impTypeStr..")"
    objc_log("Loading method:",objc_selToStr(ffi.C.method_getName(method)), impTypeStr)

    ret.imp = ffi.cast(impTypeStr, imp)

    return ret
    return ffi.cast(impTypeStr, imp)
    end

    local function _objc_readMethods(obj, cache)
    @@ -313,14 +306,13 @@ ffi.metatype("struct objc_class", {
    local methodDesc = class_getClassMethod(self, SEL(selStr))

    if ffi.cast("void*", methodDesc) > nil then
    methodDesc = _objc_readMethod(methodDesc)
    methods[selStr] = methodDesc
    method = methodDesc
    method = _objc_readMethod(methodDesc)
    methods[selStr] = method
    else
    error("Unknown selector "..selStr)
    end
    end
    local ret = method.imp(ffi.cast("id", self), SEL(selStr), ...)
    local ret = method(ffi.cast("id", self), SEL(selStr), ...)

    if ffi.istype("struct objc_object*", ret) then
    if not (selStr:sub(1,5) == "alloc" or selStr == "new") then
    @@ -331,6 +323,14 @@ ffi.metatype("struct objc_class", {
    end
    return ret
    end
    end,
    __newindex = function(self,selStr,lambda)
    selStr = selStr:gsub("_", ":")
    local className = class_getName(ffi.cast("Class", self))
    local methods = objc_instanceMethodRegistry[className]
    if not (methods == nil) then
    methods[selStr] = lambda
    end
    end
    })

    @@ -356,15 +356,14 @@ ffi.metatype("struct objc_object", {
    local methodDesc = class_getInstanceMethod(object_getClass(self), SEL(selStr))

    if ffi.cast("void*", methodDesc) > nil then
    methodDesc = _objc_readMethod(methodDesc)
    methods[selStr] = methodDesc
    method = methodDesc
    method = _objc_readMethod(methodDesc)
    methods[selStr] = method
    else
    error("Unknown selector: '"..selStr.."'")
    end
    end

    local ret = method.imp(self, SEL(selStr), ...)
    local ret = method(self, SEL(selStr), ...)

    if ffi.istype("id", ret) then
    -- Retain objects that need to be retained
  14. @fjolnir fjolnir revised this gist Mar 28, 2012. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion tlc.lua
    Original file line number Diff line number Diff line change
    @@ -24,6 +24,7 @@
    -- Creating blocks: objc_createBlock(myFunction, returnType, argTypes)
    -- returnType: An encoded type specifying what the block should return (Consult https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html for reference)
    -- argTypes: An array of encoded types specifying the argument types the block expects
    -- Both return and argument types default to void if none are passed

    local objc_debug = false
    local function objc_log(...)
    @@ -371,7 +372,6 @@ ffi.metatype("struct objc_object", {
    ret.retain()
    ret = ffi.gc(ret, CFRelease)
    end

    end
    return ret
    end
  15. @fjolnir fjolnir revised this gist Mar 28, 2012. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions tlc.lua
    Original file line number Diff line number Diff line change
    @@ -308,7 +308,7 @@ ffi.metatype("struct objc_class", {
    local methods = objc_classMethodRegistry[className]
    local method = methods[selStr]
    if method == nil then
    -- Try loading it (in case it was defined in a superclass)
    -- Try loading it (in case it was implemented in a superclass)
    local methodDesc = class_getClassMethod(self, SEL(selStr))

    if ffi.cast("void*", methodDesc) > nil then
    @@ -351,7 +351,7 @@ ffi.metatype("struct objc_object", {

    local method = methods[selStr]
    if method == nil then
    -- Try loading it (in case it was defined in a superclass)
    -- Try loading it (in case it was implemented in a superclass)
    local methodDesc = class_getInstanceMethod(object_getClass(self), SEL(selStr))

    if ffi.cast("void*", methodDesc) > nil then
  16. @fjolnir fjolnir revised this gist Mar 28, 2012. 1 changed file with 61 additions and 60 deletions.
    121 changes: 61 additions & 60 deletions tlc.lua
    Original file line number Diff line number Diff line change
    @@ -17,34 +17,34 @@

    -- Usage:
    -- Loading a class: objc_loadClass("MyClass")
    -- Creating objects: MyClass:new() or MyClass:alloc():init()
    -- Creating objects: MyClass.new() or MyClass.alloc().init()
    -- Objects returned by init* or new are automatically autoreleased
    -- Calling methods: myInstance:doThis_withThis_andThat_(this, this, that)
    -- Colons in selectors are converted to underscores
    -- Creating blocks: objc_createBlock(myFunction, returnType, argTypes)
    -- returnType: An encoded type specifying what the block should return (Consult https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html for reference)
    -- argTypes: An array of encoded types specifying the argument types the block expects

    -- Note: Currently, in order to pass an object to a method, you must append '.id' to it, this is to
    -- get the actual reference rather than the lua wrapper. This is not desirable and I will fix it asap
    -- Example: Instead of myInstance:method_(anotherInstance) you'd do myInstance:method_(anotherInstance.id)

    local objc_debug = false
    local function objc_log(...)
    if objc_debug == true then
    for i,arg in pairs({...}) do
    if i == 1 then
    output = tostring(arg)
    else
    output = output .. ", " .. tostring(arg)
    local output
    for i,arg in pairs({...}) do
    if i == 1 then
    output = tostring(arg)
    else
    output = output .. ", " .. tostring(arg)
    end
    end
    end
    io.stderr:write(output .. "\n")
    io.stderr:write(output .. "\n")
    end
    end

    ffi.cdef([[
    typedef struct objc_class *Class;
    struct objc_class {
    Class isa;
    };
    typedef struct objc_object {
    Class isa;
    } *id;
    @@ -54,33 +54,34 @@ typedef id (*IMP)(id, SEL, ...);
    typedef signed char BOOL;
    typedef struct objc_method *Method;
    id objc_getClass(const char *name);
    const char * class_getName(id cls);
    Method class_getClassMethod(id aClass, SEL aSelector);
    IMP class_getMethodImplementation(id cls, SEL name);
    Method * class_copyMethodList(id cls, unsigned int *outCount);
    Class objc_getClass(const char *name);
    const char *class_getName(Class cls);
    Method class_getClassMethod(Class aClass, SEL aSelector);
    IMP class_getMethodImplementation(Class cls, SEL name);
    Method *class_copyMethodList(Class cls, unsigned int *outCount);
    SEL method_getName(Method method);
    unsigned method_getNumberOfArguments(Method method);
    void method_getReturnType(Method method, char *dst, size_t dst_len);
    const char * method_getTypeEncoding(Method method);
    void method_getArgumentType(Method method, unsigned int index, char *dst, size_t dst_len);
    IMP method_getImplementation(Method method);
    id object_getClass(id object);
    Class object_getClass(id object);
    Method class_getInstanceMethod(id aClass, SEL aSelector);
    Method class_getClassMethod(id aClass, SEL aSelector);
    Method class_getInstanceMethod(Class aClass, SEL aSelector);
    Method class_getClassMethod(Class aClass, SEL aSelector);
    SEL sel_registerName(const char *str);
    const char* sel_getName(SEL aSelector);
    const char *object_getClassName(id obj);
    id objc_getMetaClass(const char *name);
    BOOL class_isMetaClass(id cls);
    id class_getSuperclass(id cls);
    BOOL class_isMetaClass(Class cls);
    id class_getSuperclass(Class cls);
    void free(void *ptr);
    void CFRelease(id obj);
    // http://clang.llvm.org/docs/Block-ABI-Apple.txt
    struct __block_descriptor_1 {
    @@ -144,7 +145,7 @@ end
    local SEL=objc_strToSel

    local free = ffi.C.free

    local CFRelease = ffi.C.CFRelease

    -- Stores references to method implementations
    objc_classMethodRegistry = {}
    @@ -153,7 +154,7 @@ objc_instanceMethodRegistry = {}

    -- Takes a single ObjC type encoded, and converts it to a C type specifier
    local function objc_typeEncodingToCType(aEncoding)
    i = 1
    local i = 1
    local ret = ""
    local isPtr = false

    @@ -221,14 +222,14 @@ local function objc_typeEncodingToCType(aEncoding)
    elseif c == "?" then
    ret = ret .. "void"
    elseif c == "(" then
    name = aEncoding:sub(aEncoding:find("[^=^(]+"))
    local name = aEncoding:sub(aEncoding:find("[^=^(]+"))
    if name == "?" then
    objc_log("Anonymous unions not supported: "..aEncoding)
    return nil
    end
    ret = ret .. "union "..name
    elseif c == "{" then
    name = aEncoding:sub(aEncoding:find("[^=^{]+"))
    local name = aEncoding:sub(aEncoding:find("[^=^{]+"))
    if name == "?" then
    objc_log("Anonymous structs not supported "..aEncoding)
    return nil
    @@ -246,7 +247,7 @@ local function objc_typeEncodingToCType(aEncoding)
    end

    local function _objc_readMethod(method)
    ret = {
    local ret = {
    method = method,
    argCount = method_getNumberOfArguments(method),
    }
    @@ -279,7 +280,7 @@ local function _objc_readMethod(method)

    impTypeStr = impTypeStr..")"
    objc_log("Loading method:",objc_selToStr(ffi.C.method_getName(method)), impTypeStr)
    objc_log(impTypeStr)

    ret.imp = ffi.cast(impTypeStr, imp)

    return ret
    @@ -298,18 +299,17 @@ local function _objc_readMethods(obj, cache)
    free(list)
    end

    -- Wrapper for an objc class
    objc_classWrapper = ffi.metatype("union { id id; }", {
    __index = function(proxy,selStr)
    ffi.metatype("struct objc_class", {
    __index = function(self,selStr)
    selStr = selStr:gsub("_", ":")
    return function(self, ...)
    local className = class_getName(self.id)
    return function(...)
    local className = class_getName(ffi.cast("Class", self))
    objc_log("Calling +["..className.." "..selStr.."]")
    local methods = objc_classMethodRegistry[className]
    local method = methods[selStr]
    if method == nil then
    -- Try loading it (in case it was defined in a superclass)
    local methodDesc = class_getClassMethod(self.id, SEL(selStr))
    local methodDesc = class_getClassMethod(self, SEL(selStr))

    if ffi.cast("void*", methodDesc) > nil then
    methodDesc = _objc_readMethod(methodDesc)
    @@ -319,23 +319,25 @@ objc_classWrapper = ffi.metatype("union { id id; }", {
    error("Unknown selector "..selStr)
    end
    end

    local ret = method.imp(self.id, SEL(selStr), ...)
    local ret = method.imp(ffi.cast("id", self), SEL(selStr), ...)

    if ffi.istype("struct objc_object*", ret) then
    if not (selStr:sub(1,5) == "alloc" or selStr == "new") then
    ret.retain()
    ret = ffi.gc(ret, CFRelease)
    end

    if ffi.istype("id", ret) then
    ret = objc_wrapper(ret)
    end
    return ret
    end
    end
    })

    -- Wrapper around an instance of an objc class
    objc_wrapper = ffi.metatype("struct { id id; }", {
    __index = function(proxy,selStr)
    ffi.metatype("struct objc_object", {
    __index = function(self,selStr)
    selStr = selStr:gsub("_", ":")
    return function(self, ...)
    local className = object_getClassName(ffi.cast("id", self.id))
    return function(...)
    local className = object_getClassName(ffi.cast("id", self))
    objc_log("Calling -["..className.." "..selStr.."]")
    local methods = objc_instanceMethodRegistry[className]
    -- If the class hasn't been loaded already, load it
    @@ -350,7 +352,7 @@ objc_wrapper = ffi.metatype("struct { id id; }", {
    local method = methods[selStr]
    if method == nil then
    -- Try loading it (in case it was defined in a superclass)
    local methodDesc = class_getInstanceMethod(object_getClass(self.id), SEL(selStr))
    local methodDesc = class_getInstanceMethod(object_getClass(self), SEL(selStr))

    if ffi.cast("void*", methodDesc) > nil then
    methodDesc = _objc_readMethod(methodDesc)
    @@ -361,14 +363,15 @@ objc_wrapper = ffi.metatype("struct { id id; }", {
    end
    end

    local ret = method.imp(self.id, SEL(selStr), ...)
    local ret = method.imp(self, SEL(selStr), ...)

    if ffi.istype("id", ret) then
    ret = objc_wrapper(ret)
    -- Autorelease retained objects
    if selStr:sub(1,4) == "init" or selStr == "new" then
    ret:autorelease()
    -- Retain objects that need to be retained
    if not (selStr:sub(1,4) == "init" or selStr:sub(1,4) == "copy" or selStr:sub(1,11) == "mutableCopy" or selStr == "retain" or selStr == "release") then
    ret.retain()
    ret = ffi.gc(ret, CFRelease)
    end

    end
    return ret
    end
    @@ -380,29 +383,28 @@ objc_wrapper = ffi.metatype("struct { id id; }", {
    function objc_loadClass(aClassName)
    local class = objc_getClass(aClassName)
    if(objc_classMethodRegistry[aClassName]) then
    return objc_classWrapper(class)
    return class
    end
    local metaClass = objc_getMetaClass(aClassName)

    objc_classMethodRegistry[aClassName] = objc_classMethodRegistry[aClassName] or { }
    objc_instanceMethodRegistry[aClassName] = objc_instanceMethodRegistry[aClassName] or { }

    _objc_readMethods(metaClass, objc_classMethodRegistry[aClassName])
    _objc_readMethods(ffi.cast("Class", metaClass), objc_classMethodRegistry[aClassName])
    _objc_readMethods(class, objc_instanceMethodRegistry[aClassName])

    ret = objc_classWrapper(class)
    _G[aClassName] = ret
    return ret
    _G[aClassName] = class
    return class
    end

    -- Convenience functions

    objc_loadClass("NSString")
    function objc_strToObj(aStr)
    return NSString:stringWithUTF8String_(aStr)
    return NSString.stringWithUTF8String_(aStr)
    end
    function objc_objToStr(aObj)
    local str = aObj:description():UTF8String()
    local str = aObj.description().UTF8String()
    return ffi.string(str)
    end

    @@ -412,8 +414,7 @@ end
    local objc_sharedBlockDescriptor = ffi.new("struct __block_descriptor_1")
    objc_sharedBlockDescriptor.reserved = 0;
    objc_sharedBlockDescriptor.size = ffi.sizeof("struct __block_literal_1")

    local _NSConcreteGlobalBlock = ffi.C._NSConcreteGlobalBlock
    local objc_NSConcreteGlobalBlock = ffi.C._NSConcreteGlobalBlock

    -- Wraps a function to be used with a block
    local function _objc_createBlockWrapper(lambda, retType, argTypes)
    @@ -440,7 +441,7 @@ local function _objc_createBlockWrapper(lambda, retType, argTypes)
    end

    funTypeStr = funTypeStr..")"
    objc_log(funTypeStr)
    objc_log("Created block with signature:", funTypeStr)

    ret = function(theBlock, ...)
    return lambda(...)
    @@ -454,7 +455,7 @@ function objc_createBlock(lambda, retType, argTypes)
    return nil
    end
    local block = ffi.new("struct __block_literal_1")
    block.isa = _NSConcreteGlobalBlock
    block.isa = objc_NSConcreteGlobalBlock
    block.flags = bit.lshift(1, 29)
    block.reserved = 0
    block.invoke = ffi.cast("void*", _objc_createBlockWrapper(lambda, retType, argTypes))
  17. @fjolnir fjolnir revised this gist Mar 28, 2012. No changes.
  18. @fjolnir fjolnir revised this gist Mar 28, 2012. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion tlc.lua
    Original file line number Diff line number Diff line change
    @@ -357,7 +357,7 @@ objc_wrapper = ffi.metatype("struct { id id; }", {
    methods[selStr] = methodDesc
    method = methodDesc
    else
    error("Unknown selector "..selStr)
    error("Unknown selector: '"..selStr.."'")
    end
    end

  19. @fjolnir fjolnir revised this gist Mar 28, 2012. 1 changed file with 3 additions and 2 deletions.
    5 changes: 3 additions & 2 deletions tlc.lua
    Original file line number Diff line number Diff line change
    @@ -303,8 +303,9 @@ objc_classWrapper = ffi.metatype("union { id id; }", {
    __index = function(proxy,selStr)
    selStr = selStr:gsub("_", ":")
    return function(self, ...)
    objc_log("Calling +"..selStr)
    local methods = objc_classMethodRegistry[class_getName(self.id)]
    local className = class_getName(self.id)
    objc_log("Calling +["..className.." "..selStr.."]")
    local methods = objc_classMethodRegistry[className]
    local method = methods[selStr]
    if method == nil then
    -- Try loading it (in case it was defined in a superclass)
  20. @fjolnir fjolnir revised this gist Mar 28, 2012. 1 changed file with 2 additions and 13 deletions.
    15 changes: 2 additions & 13 deletions tlc.lua
    Original file line number Diff line number Diff line change
    @@ -263,26 +263,20 @@ local function _objc_readMethod(method)
    local impTypeStr = ""..retTypeStr.." (*)("

    local argCount = ret.argCount
    local shouldCancel = false
    for j=0, argCount-1 do
    method_getArgumentType(method, j, typePtr, 512);
    local typeStr = ffi.string(typePtr)
    typeStr = objc_typeEncodingToCType(typeStr)
    -- If we encounter an unsupported type, we skip loading this method
    if typeStr == nil then
    shouldCancel = true
    break
    return nil
    end
    if j < argCount-1 then
    typeStr = typeStr..","
    end
    impTypeStr = impTypeStr..typeStr
    end

    if shouldCancel == true then
    return nil
    end

    impTypeStr = impTypeStr..")"
    objc_log("Loading method:",objc_selToStr(ffi.C.method_getName(method)), impTypeStr)
    objc_log(impTypeStr)
    @@ -432,23 +426,18 @@ local function _objc_createBlockWrapper(lambda, retType, argTypes)
    end
    local funTypeStr = ""..retType.." (*)(void *,"

    local shouldCancel = false
    for i,typeStr in pairs(argTypes) do
    typeStr = objc_typeEncodingToCType(typeStr)
    -- If we encounter an unsupported type, we skip loading this method
    if typeStr == nil then
    shouldCancel = true
    break
    return nil
    end
    if i < #argTypes then
    typeStr = typeStr..","
    end
    funTypeStr = funTypeStr..typeStr
    end

    if shouldCancel == true then
    return nil
    end
    funTypeStr = funTypeStr..")"
    objc_log(funTypeStr)

  21. @fjolnir fjolnir revised this gist Mar 28, 2012. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion tlc.lua
    Original file line number Diff line number Diff line change
    @@ -14,7 +14,7 @@
    -- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
    -- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    -- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    --

    -- Usage:
    -- Loading a class: objc_loadClass("MyClass")
    -- Creating objects: MyClass:new() or MyClass:alloc():init()
  22. @fjolnir fjolnir revised this gist Mar 28, 2012. 1 changed file with 113 additions and 13 deletions.
    126 changes: 113 additions & 13 deletions tlc.lua
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,36 @@
    -- TLC - The Tiny Lua Cocoa bridge
    -- Note: Only tested on x86_64 & OS X >=10.7.3

    -- Copyright (c) 2012, Fjölnir Ásgeirsson

    -- Permission to use, copy, modify, and/or distribute this software for any
    -- purpose with or without fee is hereby granted, provided that the above
    -- copyright notice and this permission notice appear in all copies.

    -- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
    -- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
    -- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
    -- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
    -- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
    -- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    -- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    --
    -- Usage:
    -- Loading a class: objc_loadClass("MyClass")
    -- Creating objects: MyClass:new() or MyClass:alloc():init()
    -- Objects returned by init* or new are automatically autoreleased
    -- Calling methods: myInstance:doThis_withThis_andThat_(this, this, that)
    -- Colons in selectors are converted to underscores
    -- Creating blocks: objc_createBlock(myFunction, returnType, argTypes)
    -- returnType: An encoded type specifying what the block should return (Consult https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html for reference)
    -- argTypes: An array of encoded types specifying the argument types the block expects

    -- Note: Currently, in order to pass an object to a method, you must append '.id' to it, this is to
    -- get the actual reference rather than the lua wrapper. This is not desirable and I will fix it asap
    -- Example: Instead of myInstance:method_(anotherInstance) you'd do myInstance:method_(anotherInstance.id)

    local objc_debug = false
    function objc_log(...)
    local function objc_log(...)
    if objc_debug == true then
    for i,arg in pairs({...}) do
    if i == 1 then
    @@ -25,14 +54,12 @@ typedef id (*IMP)(id, SEL, ...);
    typedef signed char BOOL;
    typedef struct objc_method *Method;
    SEL sel_registerName(const char *str);
    id objc_getClass(const char *name);
    const char * class_getName(id cls);
    Method class_getClassMethod(id aClass, SEL aSelector);
    IMP class_getMethodImplementation(id cls, SEL name);
    Method * class_copyMethodList(id cls, unsigned int *outCount);
    SEL method_getName(Method method);
    unsigned method_getNumberOfArguments(Method method);
    void method_getReturnType(Method method, char *dst, size_t dst_len);
    @@ -44,6 +71,7 @@ id object_getClass(id object);
    Method class_getInstanceMethod(id aClass, SEL aSelector);
    Method class_getClassMethod(id aClass, SEL aSelector);
    SEL sel_registerName(const char *str);
    const char* sel_getName(SEL aSelector);
    const char *object_getClassName(id obj);
    @@ -52,12 +80,23 @@ id objc_getMetaClass(const char *name);
    BOOL class_isMetaClass(id cls);
    id class_getSuperclass(id cls);
    double objc_msgSend_fpret(id self, SEL op, ...);
    id objc_msgSend(id theReceiver, SEL theSelector, ...);
    void objc_msgSend_stret(void * stretAddr, id theReceiver, SEL theSelector, ...);
    void free(void *ptr);
    // http://clang.llvm.org/docs/Block-ABI-Apple.txt
    struct __block_descriptor_1 {
    unsigned long int reserved; // NULL
    unsigned long int size; // sizeof(struct __block_literal_1)
    }
    struct __block_literal_1 {
    struct __block_literal_1 *isa;
    int flags;
    int reserved;
    void *invoke;
    struct __block_descriptor_1 *descriptor;
    }
    struct __block_literal_1 *_NSConcreteGlobalBlock;
    // NSObject dependencies
    typedef double CGFloat;
    typedef struct CGPoint { CGFloat x; CGFloat y; } CGPoint;
    @@ -73,6 +112,7 @@ typedef struct _NSZone NSZone;
    struct _NSStringBuffer {};
    ]])


    local objc_getClass = ffi.C.objc_getClass
    local objc_getMetaClass = ffi.C.objc_getMetaClass

    @@ -112,7 +152,7 @@ objc_instanceMethodRegistry = {}


    -- Takes a single ObjC type encoded, and converts it to a C type specifier
    function objc_typeEncodingToCType(aEncoding)
    local function objc_typeEncodingToCType(aEncoding)
    i = 1
    local ret = ""
    local isPtr = false
    @@ -251,7 +291,7 @@ local function _objc_readMethod(method)
    return ret
    end

    function _objc_readMethods(obj, cache)
    local function _objc_readMethods(obj, cache)
    local count = ffi.new("unsigned int[1]")
    local list = class_copyMethodList(obj, count)
    for i=0, count[0]-1 do
    @@ -311,16 +351,14 @@ objc_wrapper = ffi.metatype("struct { id id; }", {
    error("Could not find class "..className)
    end
    end
    --objc_log(self.id, object_getClassName(ffi.cast("id", self.id)), selStr, methods)

    local method = methods[selStr]
    if method == nil then
    -- Try loading it (in case it was defined in a superclass)
    local methodDesc = class_getInstanceMethod(object_getClass(self.id), SEL(selStr))

    if ffi.cast("void*", methodDesc) > nil then
    print(methodDesc)
    methodDesc = _objc_readMethod(methodDesc)
    print(methodDesc)
    methods[selStr] = methodDesc
    method = methodDesc
    else
    @@ -372,3 +410,65 @@ function objc_objToStr(aObj)
    local str = aObj:description():UTF8String()
    return ffi.string(str)
    end


    -- Blocks

    local objc_sharedBlockDescriptor = ffi.new("struct __block_descriptor_1")
    objc_sharedBlockDescriptor.reserved = 0;
    objc_sharedBlockDescriptor.size = ffi.sizeof("struct __block_literal_1")

    local _NSConcreteGlobalBlock = ffi.C._NSConcreteGlobalBlock

    -- Wraps a function to be used with a block
    local function _objc_createBlockWrapper(lambda, retType, argTypes)
    -- Build a function definition string to cast to
    retType = retType or "v"
    argTypes = argTypes or {"v"}

    retType = objc_typeEncodingToCType(retType)
    if retType == nil then
    return nil
    end
    local funTypeStr = ""..retType.." (*)(void *,"

    local shouldCancel = false
    for i,typeStr in pairs(argTypes) do
    typeStr = objc_typeEncodingToCType(typeStr)
    -- If we encounter an unsupported type, we skip loading this method
    if typeStr == nil then
    shouldCancel = true
    break
    end
    if i < #argTypes then
    typeStr = typeStr..","
    end
    funTypeStr = funTypeStr..typeStr
    end

    if shouldCancel == true then
    return nil
    end
    funTypeStr = funTypeStr..")"
    objc_log(funTypeStr)

    ret = function(theBlock, ...)
    return lambda(...)
    end
    return ffi.cast(funTypeStr, ret)
    end

    -- Creates a block and returns it typecast to 'id'
    function objc_createBlock(lambda, retType, argTypes)
    if not lambda then
    return nil
    end
    local block = ffi.new("struct __block_literal_1")
    block.isa = _NSConcreteGlobalBlock
    block.flags = bit.lshift(1, 29)
    block.reserved = 0
    block.invoke = ffi.cast("void*", _objc_createBlockWrapper(lambda, retType, argTypes))
    block.descriptor = objc_sharedBlockDescriptor

    return ffi.cast("id", block)
    end
  23. @fjolnir fjolnir revised this gist Mar 27, 2012. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions tlc.lua
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,5 @@
    -- TLC - The Tiny Lua Cocoa bridge

    local objc_debug = false
    function objc_log(...)
    if objc_debug == true then
  24. @fjolnir fjolnir renamed this gist Mar 27, 2012. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  25. @fjolnir fjolnir revised this gist Mar 27, 2012. 1 changed file with 6 additions and 0 deletions.
    6 changes: 6 additions & 0 deletions objc.lua
    Original file line number Diff line number Diff line change
    @@ -316,7 +316,9 @@ objc_wrapper = ffi.metatype("struct { id id; }", {
    local methodDesc = class_getInstanceMethod(object_getClass(self.id), SEL(selStr))

    if ffi.cast("void*", methodDesc) > nil then
    print(methodDesc)
    methodDesc = _objc_readMethod(methodDesc)
    print(methodDesc)
    methods[selStr] = methodDesc
    method = methodDesc
    else
    @@ -364,3 +366,7 @@ objc_loadClass("NSString")
    function objc_strToObj(aStr)
    return NSString:stringWithUTF8String_(aStr)
    end
    function objc_objToStr(aObj)
    local str = aObj:description():UTF8String()
    return ffi.string(str)
    end
  26. @fjolnir fjolnir revised this gist Mar 27, 2012. 1 changed file with 6 additions and 1 deletion.
    7 changes: 6 additions & 1 deletion objc.lua
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    local objc_debug = true
    local objc_debug = false
    function objc_log(...)
    if objc_debug == true then
    for i,arg in pairs({...}) do
    @@ -54,6 +54,8 @@ double objc_msgSend_fpret(id self, SEL op, ...);
    id objc_msgSend(id theReceiver, SEL theSelector, ...);
    void objc_msgSend_stret(void * stretAddr, id theReceiver, SEL theSelector, ...);
    void free(void *ptr);
    // NSObject dependencies
    typedef double CGFloat;
    typedef struct CGPoint { CGFloat x; CGFloat y; } CGPoint;
    @@ -99,6 +101,8 @@ local function objc_strToSel(str)
    end
    local SEL=objc_strToSel

    local free = ffi.C.free


    -- Stores references to method implementations
    objc_classMethodRegistry = {}
    @@ -255,6 +259,7 @@ function _objc_readMethods(obj, cache)

    cache[selStr] = _objc_readMethod(method)
    end
    free(list)
    end

    -- Wrapper for an objc class
  27. @fjolnir fjolnir revised this gist Mar 27, 2012. 1 changed file with 9 additions and 13 deletions.
    22 changes: 9 additions & 13 deletions objc.lua
    Original file line number Diff line number Diff line change
    @@ -1,11 +1,11 @@
    local objc_debug = false
    local objc_debug = true
    function objc_log(...)
    if objc_debug == true then
    for i,str in pairs({...}) do
    for i,arg in pairs({...}) do
    if i == 1 then
    output = str
    output = tostring(arg)
    else
    output = output .. ", " .. str
    output = output .. ", " .. tostring(arg)
    end
    end
    io.stderr:write(output .. "\n")
    @@ -282,17 +282,9 @@ objc_classWrapper = ffi.metatype("union { id id; }", {

    if ffi.istype("id", ret) then
    ret = objc_wrapper(ret)
    -- Retain autoreleased objects (until the proxy is collected by lua gc)
    --if not(selStr:sub(1,4) == "init" or selStr == "new") then
    ret:retain()
    --end
    end
    return ret
    end
    end,
    __gc = function(proxy)
    objc_log("Releasing!", proxy.id)
    proxy:release()
    end
    })

    @@ -330,7 +322,11 @@ objc_wrapper = ffi.metatype("struct { id id; }", {
    local ret = method.imp(self.id, SEL(selStr), ...)

    if ffi.istype("id", ret) then
    return objc_wrapper(ret)
    ret = objc_wrapper(ret)
    -- Autorelease retained objects
    if selStr:sub(1,4) == "init" or selStr == "new" then
    ret:autorelease()
    end
    end
    return ret
    end
  28. @fjolnir fjolnir revised this gist Mar 27, 2012. 1 changed file with 22 additions and 3 deletions.
    25 changes: 22 additions & 3 deletions objc.lua
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,14 @@
    local objc_debug = false
    function objc_log(...)
    if objc_debug == true then
    print(...)
    for i,str in pairs({...}) do
    if i == 1 then
    output = str
    else
    output = output .. ", " .. str
    end
    end
    io.stderr:write(output .. "\n")
    end
    end

    @@ -58,6 +65,8 @@ typedef long NSInteger;
    typedef unsigned long NSUInteger;
    typedef struct _NSRange { NSUInteger location; NSUInteger length; } NSRange;
    typedef struct _NSZone NSZone;
    // NSString dependencies
    struct _NSStringBuffer {};
    ]])

    local objc_getClass = ffi.C.objc_getClass
    @@ -180,7 +189,7 @@ function objc_typeEncodingToCType(aEncoding)
    end
    ret = ret .. "struct "..name
    else
    error("Error! type encoding '"..aEncoding.."' is not supported")
    objc_log("Error! type encoding '"..aEncoding.."' is not supported")
    return nil
    end

    @@ -202,6 +211,9 @@ local function _objc_readMethod(method)

    method_getReturnType(method, typePtr, 512)
    local retTypeStr = objc_typeEncodingToCType(ffi.string(typePtr))
    if retTypeStr == nil then
    return nil
    end
    local impTypeStr = ""..retTypeStr.." (*)("

    local argCount = ret.argCount
    @@ -292,6 +304,7 @@ objc_wrapper = ffi.metatype("struct { id id; }", {
    local className = object_getClassName(ffi.cast("id", self.id))
    objc_log("Calling -["..className.." "..selStr.."]")
    local methods = objc_instanceMethodRegistry[className]
    -- If the class hasn't been loaded already, load it
    if methods == nil then
    objc_loadClass(className)
    methods = objc_instanceMethodRegistry[className]
    @@ -314,7 +327,6 @@ objc_wrapper = ffi.metatype("struct { id id; }", {
    end
    end

    --objc_log(self.id, selStr, ...)
    local ret = method.imp(self.id, SEL(selStr), ...)

    if ffi.istype("id", ret) then
    @@ -344,3 +356,10 @@ function objc_loadClass(aClassName)
    _G[aClassName] = ret
    return ret
    end

    -- Convenience functions

    objc_loadClass("NSString")
    function objc_strToObj(aStr)
    return NSString:stringWithUTF8String_(aStr)
    end
  29. @fjolnir fjolnir revised this gist Mar 27, 2012. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion objc.lua
    Original file line number Diff line number Diff line change
    @@ -168,7 +168,7 @@ function objc_typeEncodingToCType(aEncoding)
    elseif c == "(" then
    name = aEncoding:sub(aEncoding:find("[^=^(]+"))
    if name == "?" then
    objc_log("Anonymous structs not unions: "..aEncoding)
    objc_log("Anonymous unions not supported: "..aEncoding)
    return nil
    end
    ret = ret .. "union "..name
  30. @fjolnir fjolnir renamed this gist Mar 27, 2012. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.