introduction to loc

Post on 05-Jul-2015

928 Views

Category:

Technology

2 Downloads

Preview:

Click to see full reader

DESCRIPTION

Loc (Lua to Objective-C) is a bridge of type conversion between Lua and Objective-C. This presentation shows the design idea of Loc.

TRANSCRIPT

Introduction to Loc A bridge between Lua and Objective-C

Data Type Mapping

Lua Type Objective-C Type

LUA_TNIL nil

LUA_TBOOLEAN BOOL (? NSNumber)

LUA_TLIGHTUSERDATA

LUA_TNUMBER NSNumber

LUA_TSTRING NSString

LUA_TTABLE NS(Mutable)Dictionary (? NSArray)

LUA_TFUNCTION C Function Pointer (Lua Function)

LUA_TUSERDATA

(?) NSObject

Table Lua Table type implements associative arrays.

It can be used as Array with numeric index:

local array = {0,1, "string3", true};

or Dictionary with string key:

local dict = {"hello"="world", 8="storm"};!

Pound(#) operator would return the length of table if table is Array, but it does not count string key/value pairs.

print(#array); 4

Metatable

Metatable is still a table.

It is attached to other Lua type to:

Ø  Identify a value as a “Class”

Ø  Provide default behaviors by Metamethods

Set/Get Metatable

•  Lua API

getmetatable (object)!

setmetatable (table, metatable)!

!(In Lua, only able to set metatable on table)!

•  C API

int lua_setmetatable (lua_State *L, int objindex)!

int lua_getmetatable (lua_State *L, int objindex)

Metamethod

Simple explain: they are a set of special keys in metatable.

The values assigned with those keys will automatically trigger in certain situation.

Technical explain: they are Operator Overloading

__add, __sub, __mul, __div, __mod, __pow, __unm, __concat, __len, __eq, __lt, __le, __index, __newindex, __call

__index

Trigger

• Try to get value from key which does not exist in original table

Metametahod Value

• A function • A Table

Effect

• Call __index(table, key) • Return __index[key]

__newindex

Trigger

• Try to set value to key which does not exist in original table

Metametahod Value

• A function • A Table

Effect

• Call __newindex(table, key, value) • __newindex[key] = value;

__call

Trigger • Use table as function, and call with ()

Metametahod Value

• A function

Effect • Call __call(table, …); … are arguments

Colon(:) vs Dot(.)

Lua is not Class based Object oriented language, this or self is not reserved keyword. When call a method on object(table), inside method it don’t know which object it is using. Programmer has to manually pass it to method:

obj.count(obj);!

When define the method, we also need to reserve a argument for it, and we could define the argument name as this or self.

function count(self) {!

return #self;!

}!

Colon(:) vs Dot(.)

Lua provide a syntax sugar, we could use colon(:) to call method, and it will automatically pass the caller as first argument.

obj:count();

However, when define the method, we still need to reserve first position of argument for caller.

Userdata

The userdata type allows arbitrary C data to be stored in Lua variables.

void *lua_newuserdata (lua_State *L, size_t size)

It allocate memory with given size, and return pointer to that memory address.

It’s very similar to C void *malloc(size_t); except with above API, the memory is allocated in Lua, hence Lua GC will automatically free it, if there is no reference on it.

Metatable on Userdata

Lua has not predefined any operations for Userdata, except assignment and equality test.

Userdata does not contain any key, hence any get/set of key would always trigger metamethod. Developer could define a custom metatable and set to userdata to provide certain functionalities.

E.g.: when set value on key, with __newindex we could redirect to set value on relative property; when compare two user data, with __eq we could compare not only the address but also the content.

Light Userdata

A light userdata is a value that represents a C pointer (i.e. a void * value).

void lua_pushlightuserdata (lua_State *L, void *p)

Lua only hold the pointer to a memory, the program out of Lua should handle the memory manager of that data.

Light Userdata vs Userdata

All the light userdata share the same metatable. Push A to Lua as light userdata;

Set MTX on A as metatable;

Push B to Lua as light userdata;

Get metatable of B, you will get MTX, not nil;

Set MTY on B as metatable;

Metatable of A will also change to MTY

Userdata has it’s own metatable, and programmer need to set metatable on each new created userdata

Loc Design

1.  Create metatable, bind C functions to metamethods

2.  Create userdata, set the address of object to it

3.  Set metatable on userdata

4.  Push userdata to lua

Whenever we need to push objective-C object to Lua, we do step 2-4

Use Light Userdata

" pushid

lua_pushlightuserdata(L, self);!

luaL_getmetatable(L, name);

lua_setmetatable(L, -2);

" toid

return (id)lua_touserdata(L, idx);

Use Userdata

" pushid

id *ud = (id*)lua_newuserdata(L, sizeof(id));!

*ud = self;!

luaL_getmetatable(L, name);

lua_setmetatable(L, -2);

" toid

return *((id*)lua_touserdata(L, idx));

Loc Trigger on Setter

Lua statement

• object.propertyName = value;

Trigger __newIndex

• __newindex(object, propertyName, value);

Call to bond C Function

• Retrieve userdata back to Object, get other info

Call Objective-C

• [object setValue:value forKey:propertyName];

Loc Trigger on Getter

Object has data members, and method members.

When using Lua syntax to request member with name, inside __index method, only the name is provided, we don’t know the result should be a value, or a function which would accept more arguments. Because we don’t know if there are parenthesis after the name or not.

So in __index, Loc always return a function (use table with __call metamethod to implement a functor). Later call on that function, if there is no argument, we treat as property.

Loc Trigger on Method Call

Lua statement

• value = object:propertyName(); • result = object:methodName(arguments);

Trigger __newIndex

• Create new table; save Name in table; set metatable

Trigger __call • Retrieve object; get name from table; parse arugments

Trigger __call

• [object valueForKey:propertyName]; • Use NSInvocaton to reflect the method call

Loc Function Call Process

object:methodName(arguments);!

__index(object, methodName)!

functor = { _key = methodName };!

setMetatable(functor)!

return functor;!

Loc Function Call Process

object:functor(arguments);!

functor(object, arguments)!

__call(functor, object, arguments)!

methodName = functor[_key];!

selector = convert(methodName);!

invocation = NSInvocatoin(...);!

invocation.invoke();!

return invocation.result;!

NSDictionary & NSArray

NSDictionary and NSArray are well-defined system class. The functionalities required are more clear than user defined classes. So we don’t need to use reflection for them.

Loc define C functions to directly map to relative instance methods.

This is done by setting table, which contains a set of C Functions, on __index of metatable, and called by colon(:) syntax.

LocDictionary

Selector Functions __index

Table

get(k) objectForKey:

set(k,v) setObject:forKey:

count() count

… …

Some methods may would allowed for NSMutableDictionary

LocArray

Selector Functions __index

Table

get(i) objectAtIndex:

add(o) addObject:

count() count

… …

Some methods may would allowed for NSMutableArray The index is 1-based, it will convert to 0-based in methods

LocLuaLib "   It is a set of utility methods as Lua Library.

"   It register as global table loc.

Method Library loc

loc

toclass(str) NSClassFromString()

todictionary(t) loc_todictionary()

toarray(t) loc_toarray()

Q & A

You may also like to know

Registry: http://www.lua.org/pil/27.3.1.html Special place to share global data between C functions

Privacy: http://www.lua.org/pil/15.2.html Use local table as key for other table

Metatable protection: http://www.lua.org/pil/13.3.html __metatable

C Library: http://www.lua.org/pil/26.2.html Register a set of C Functions as Lua Library

top related