GithubHelp home page GithubHelp logo

tlc's Introduction

TLC - The Tiny Lua Cocoa Bridge

TLC is a very compact and minimal Objective-C bridge for LuaJIT. Written by Fjõlnir Ásgeirsson

Simple Example

local objc = require("objc")
objc.loadFramework("AppKit")
pool = objc.NSAutoreleasePool:new()
objc.NSSpeechSynthesizer:new():startSpeakingString(objc.NSStr("Hello From Lua!"))
os.execute("sleep "..2)

Mini-Documentation

TLC supports the following:

  • Loading frameworks
  • Accessing Objective-C objects
  • Creating Objective-C classes
  • Calling methods on said objects
  • Creating blocks from Lua functions
  • Converting the basic lua types to objects (Explicitly)
  • Loading BridgeSupport files

TLC Does not yet support the following:

  • Calling methods that take a variable number of arguments
  • Defining variadic blocks, methods or callbacks, or ones that take pass-by-value(non-pointer) structs or unions. (A limitation of LuaJIT FFI)

Loading TLC

local objc = require("objc")

Loading frameworks

objc.loadFramework("Foundation")

-- You can also use BridgeSupport
-- It is slower, but you get access to all C types, functions & constants automatically
local bs = require("objc.BridgeSupport")
bs.loadFramework("Foundation")
-- You can then access constants using bs
myView.center = bs.CGPointZero

Accessing Objective-C objects

local NSString = objc.NSString

Calling Methods

local myStr = NSString:stringWithUTF8String("I am an NSString.")

-- Calling selectors with multiple arguments requires replacing the colons with underscores
-- Except the ones at the end, they are optional.
-- Example selector:with:multiple:parameters: => selector_with_multiple_parameters()
--         selectorWithAnonymousParams:::: => selectorWithAnonymousParams()
local anObject = MyObject:selector_with_multiple_parameters(arg1, arg2, arg3, arg4)

Converting the Basic Lua Types to Objects

-- If you know the type of the variable you want to convert you should use these functions
local string     = NSStr("foobar")
local number     = NSNum(123)
local array      = NSArr({"a","b","c"})
local dictionary = NSDic({ a=1, b=2, c=3 })
-- If not,
-- The Obj() function takes an arbitrary value and determines the correct class to convert it to
local object = Obj(anyVariable)

Subclassing & Extending of Classes

-- This creates a class and registers it with the runtime (it is also accessible with objc.MyClass after creation)
-- The dictionary specifies an instance variable of type int(type encoding: i)
-- To learn about type encodings read https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html
local MyClass = objc.createClass(objc.NSObject, "MyClass", { ivar="i" })

-- Creates an init method returning an object(@) and taking as arguments an object(@) and a selector(:)
-- All methods must take self and selector as their first two arguments
objc.addMethod(MyClass, objc.SEL("init"), function(self, sel)
	print("Creating an instance of", self:class())
	objc.setIvar(self, "anIvar", 123)
	return objc.callSuper(self, sel)
end, "@@:")

-- Add a getter for 'ivar'
objc.addMethod(MyClass, objc.SEL("ivar"), function(self, sel)
	return objc.getIvar(self, "ivar")
end, "i@:")
-- Add a setter for 'ivar'
objc.addMethod(MyClass, objc.SEL("setIvar:"), function(self, sel, anIvar)
	objc.setIvar(self, "ivar", anIvar)
end, "v@:i")

-- 'instance' is an object pointer usable on the lua side as well as the objective-c side
local instance = MyClass:alloc():init()
instance:setIvar(123)
print(instance:ivar())

Creating Blocks from Lua Functions

-- To create a block you call createBlock with it's type encoding (Default being void return and no argument)
-- A block returning an integer and taking one object and one double as arguments
local block = objc.createBlock(function(object, double)
	print("I was passed these arguments: ", object, double)
	return 123
end, "i@d")

(Dirty Secret Trick)

-- If you don't want to type 'objc.' before using a class you can set the global namespace to use it as a fallback
setmetatable(_G, {__index=objc})
-- And then you can simply write the class names without the 'objc.' prefix
obj = CoolClass:doThings()

tlc's People

Contributors

fjolnir avatar granpc avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tlc's Issues

License?

Looking at init.lua, it looks like this project is distributed under the ISC license. Is that correct?

Address boundary error

State: updated TLC, luajit 2.0.1 from macports on 10.7 system, window.lua is at the same fs level of objc/ folder.

I get an Address boundary error after the call to

bs.loadFramework("AppKit", true)

while the call to Foundation returns just fine.

I'm able to run the Cocoa application with TLC using plain objc.loadFramework() rather than BridgeScript but having to define each constant after looking their value in header is quite uncomfortable.

Here's the actual output with backtrace:

me@biboop ~/D/D/L/TLC> luajit window.lua
fish: Job 1, 'luajit window.lua ' terminated by signal SIGSEGV (Address boundary error)
me@biboop ~/D/D/L/TLC> gdb luajit
GNU gdb 6.3.50-20050815 (Apple version gdb-1824) (Wed Feb  6 22:51:23 UTC 2013)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "x86_64-apple-darwin"...Reading symbols for shared libraries .. done

(gdb) r window.lua
Starting program: /opt/local/bin/luajit window.lua
Reading symbols for shared libraries +........................ done
Reading symbols for shared libraries ..... done
Reading symbols for shared libraries .... done
Reading symbols for shared libraries ................................ done
Reading symbols for shared libraries ................................................................... done
Reading symbols for shared libraries .. done
Reading symbols for shared libraries . done
Reading symbols for shared libraries . done
Reading symbols for shared libraries ........ done
Reading symbols for shared libraries . done

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: 13 at address: 0x0000000000000000
0x00007fff85ffbfe6 in libunwind::CompactUnwinder_x86_64<libunwind::LocalAddressSpace>::stepWithCompactEncodingFrameless ()
(gdb) bt
#0  0x00007fff85ffbfe6 in libunwind::CompactUnwinder_x86_64<libunwind::LocalAddressSpace>::stepWithCompactEncodingFrameless ()
#1  0x00007fff85ffa20c in libunwind::CompactUnwinder_x86_64<libunwind::LocalAddressSpace>::stepWithCompactEncoding ()
#2  0x00007fff85ffa171 in libunwind::UnwindCursor<libunwind::LocalAddressSpace, libunwind::Registers_x86_64>::step ()
#3  0x00007fff85ff9931 in _Unwind_RaiseException ()
#4  0x0000000100006fca in main ()
(gdb)

Organization of files and Frameworks

Please consider organizing the project as follows:

/tlc
 + /objc
 |  +  /init.lua # ObjC core definitions, current tlc - framework specific types and functions
 |  +  /Foundation.lua # Foundation specific ffi.load and convinience functions such as NSString, NSArray and NSObject utils
 |  +  /CoreFoundation.lua # Same for CoreFoundation framework
 |  +  /AppKit.lua # etc.
 |  +  ... 
 |
 + ...

This way frameworks can be loaded using require, eg: require "objc.AppKit" which can also ensure that dependent frameworks are loaded by requiring the Foundation frameworks. The objc.loadFramework function can require the framework file if it exists and then fall back to the current implementation for other frameworks. Keeping the files in the objc directory will also make installing the project much easier.

How to pass objects back and forth through the bridge?

Is it posible to do something like this:

MyClass *myObj = [[MyClass alloc] init];
lua_pushlightuserdata (L, myObj);
lua_setglobal(L, "myObj");
lua_dostring(L,
  "local objc = require'objc' \n"
  "local ffi = require'ffi' \n"
  "local myLuaObj = ffi.cast(ffi.typeof'id', myObj) \n"
  "myLuaObj:doSomething() \n"
);

I would like to be able to pass objects back and forth between ObjC and the Lua virtual machine.

Struct CGSize has no member named 'width'

Using the current trunk, I'm getting the following error when attempting to access the "width" property of a CGSize struct:

'struct CGSize' has no member named 'width'

Adding the following typedef fixes the problem:

typedef struct CGSize { CGFloat width; CGFloat height; } CGSize;

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.