iOS中Lua脚本的应用

2,403 views
2,068 views

Published on

How To Use Lua In iOS

Published in: Education, Technology
0 Comments
5 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
2,403
On SlideShare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
35
Comments
0
Likes
5
Embeds 0
No embeds

No notes for slide

iOS中Lua脚本的应用

  1. 1. iOS中Lua脚本的应用 Proteas 2012-07-23 proteas.wang@gmail.com
  2. 2. 概要 • 为什么要在应用中引入脚本? • 为什么是 Lua ? • 使用 Lua 开发应用的几种模式 • Hello Lua • Meta-*: Lua 与 Objective-C 集成的原理 • wax 框架及其本身的一些问题 • Demos • 其它 • 目前没有解决的问题
  3. 3. 为什么要在应用中引入脚本? • 目前在进行开发应用时遇到的一些问题 – UI 变化 – 业务逻辑变化 – 数据源不灵活 • 如何处理 UI 变化? • 如何处理业务逻辑变化? • 如何解决数据源不灵活的问题? • ObjC 语言的问题(编译执行) * Warning:使用 PList 作为配置文件时要谨 慎
  4. 4. 为什么是 Lua ? • 设计目标:嵌入到应用程序中(嵌入式) • 体积小:100~200K • 最快的脚本语言(非 JIT) • 简洁的 API • 动态语言 • Domain Specific Language * 编程语言的哲学: – 编程语言是否都差不多? – Assembly,C,C++,Java/C#,Python, Ruby,Common Lisp – 代码与数据的统一
  5. 5. 使用 Lua 开发应用的几种模式 • Lua作为配置文件 ,为宿主语言应用 提供参数 宿主语言 Lua • 宿主语言作为底层 库,Lua 作为逻辑描 述 Lua 宿主语言 * Lua VS. Plist or XML Corona SDK
  6. 6. Hello Lua:什么是 Lua • Lua是一种脚本编程语言,于1994年,由巴西里 约热内卢天主教大学的研究人员设计开发, “Lua”这个名字是葡萄牙语单词 “月亮”。 • 与一般脚本语言如 PHP、Perl、JavaScript 等不 同,Lua被称为是一种嵌入式脚本语言,Lua最著 名的应用是在暴雪公司的网络游戏 魔兽世界 中。 – 《World of Warcraft Programming》 • Lua最引人注目的特点: – 以极小 的体积和简单 的语法提供相对全面的功能。 – 以简洁 的API实现与宿主语言最方便 的接口。 • 在服务器端也有着广泛的应用
  7. 7. Hello Lua:为什么称为“嵌入式” • Lua语言可以独立进行编程,但这不是其主要的 使用方式。Lua虽然有动态、灵活的语法提供强 大的功能,但并不像 Java、Python 等一样有一 个完善的库(但仍存在一定数量的第三方库), 这不是缺陷,而是和其定位有关。 • Lua最典型的用法,是作为一个库,嵌入 到其他 大型语言(称之为宿主语言 )的应用程序之中, 为应用程序提供参数配置或逻辑描述等功能,带 来前所未有的灵活性。 • Lua常见的宿主语言有:C/C++,Java,.NET, 甚至脚本语言如PHP,Ruby等。
  8. 8. Hello Lua:工作流程 • 1.宿主语言建立Lua解释器对象。 • 2.将宿主语言实现的Lua扩展(若有),如函数等 ,注册到Lua解释器中,供其使用。 • 3.读入Lua源程序或预先编译后的Lua程序(可以 从文件、字符串、网络等任意来源)。 • 4.执行读入的Lua程序。
  9. 9. Hello Lua:lua_State
  10. 10. Hello Lua:变量 • Lua 是动态语言,变量没有类型,存储的值才有类型 • 八个基本类型 * 点对 • var = 4 • var = “hello” • var = {x = 10, y = 20} • a, b = 1, 2
  11. 11. Hello Lua:控制结构 • 条件判断:if • 迭代: – while – repeat – for
  12. 12. Hello Lua:控制结构-If • if Statement if a <= 0 then a = a + 1 end if a < 0 then a = a + 1 elseif a > 0 then a = a – 1 else a = 0 end Nested if-else statement Simple if statement
  13. 13. Hello Lua:控制结构-While • While Loop Lua first tests the while condition, if it is false then the loop ends, otherwise it executes the body a = {1,2,3,4,5} i = 1 while a[i] do print(a[i]) i = i + 1 end Output: 1,2,3,4,5
  14. 14. Hello Lua:控制结构-Repeat • Repeat Repeat-until statement repeats its body until the condition is true. This ensures that the body of the loop is executed at least once. a = 0 repeat a = a + 1 print(a) until a > 10 Output: 1,2,3,4,5,6,7,8,9,10,11 This block always executes at least once
  15. 15. Hello Lua:控制结构-Numeric Loop • Numeric For Loop for i=1,10,1 do print(i) end Output: 1,2,3,4,5,6,7,8,9,10 Initial condition Evaluate to Increment by
  16. 16. Hello Lua:控制结构-Generic Loop • Generic For Loop – Allows you to traverse all values returned by an iterator function colors = {“red”, “green”, “blue”} for i,v in ipairs(colors) do print(i,v) end Output: 1 red, 2 green, 3 blue Iterator Functionindex value
  17. 17. Hello Lua:函数 • 函数是第一类型 • 定义函数 • 调用 function add(a, b) c = a + b return c end x = add(1, 2) print(x) 输出:3
  18. 18. Hello Lua:Closure • Closures – A function which returns a function – Has full access to local variables – This allows Lua to implement functional programming function newCounter() local i = 0 return function() i = i + 1 return i end end Anonymous function c1 = newCounter() print(c1()) --> 1 print(c1()) --> 2 c2 = newCounter() print(c2()) --> 1 print(c1()) --> 3 print(c2()) --> 2 * UpValues:lobject.h(231~)
  19. 19. Hello Lua:数据结构-Table • 创建:t = {1, 2,3, 4, 5} • 取值:t[1], t[2] • 从 1 开始索引 • t = {apple="green", orange="orange", banana="yellow"} • t[“apple”], t[“orange”], t[“banana”] • t = { 2,4,6, language="Lua", version="5.1" }
  20. 20. Hello Lua:Meta Table • t = {1, 2, 3} • mt = {} • setmetatable(t, mt) • 数据结构:lobject.h(338~348) * 如果不是开源代码呢?
  21. 21. Hello Lua:Meta Methods > x = { value = 3 } -- our object > > mt = { __add = function (a, b) >> return { value = a.value + b.value } >> end } -- metatable containing event callbacks > > a = x + x -- without a metatable this is just a regular table stdin:1: attempt to perform arithmetic on global `x' (a table value) stack traceback: stdin:1: in main chunk [C]: ? > > setmetatable(x, mt) -- attach our metamethods to our object > > a = x + x -- try again > print(a.value) 6
  22. 22. Hello Lua:Meta Methods 原型 作用 __index Control 'prototype' inheritance. if the value is a function, the function is called, passing in the table and the key; the return value of that function is returned as the result. __newindex Control property assignment. When calling myTable[key] = value, if the metatable has a __newindex key pointing to a function, call that function, passing it the table, key, and value. __call Treat a table like a function. When a table is followed by parenthesis such as myTable( 'foo' ) and the metatable has a __call key pointing to a function, that function is invoked (passing any specified arguments) and the return value is returned. __add Addition __sub Subtraction … … * 横向比较
  23. 23. Hello Lua:Meta Methods -- create a namespace Window = {} -- create the prototype with default values Window.prototype = {x = 0, y = 0, width = 100, height = 100, } -- create a metatable Window.mt = {} -- declare the constructor function function Window.new (o) setmetatable(o, Window.mt) return o end
  24. 24. Hello Lua:Meta Methods Now, we define the __index metamethod: Window.mt.__index = function (table, key) return Window.prototype[key] end After that code, we create a new window and query it for an absent field: w = Window.new{x = 10, y = 20} print(w.width) --> 100 When Lua detects that w does not have the requested field, but has a metatable with an __index field, Lua calls this __index metamethod, with arguments w (the table) and "width" (the absent key). The metamethod then indexes the prototype with the given key and returns the result.
  25. 25. Hello Lua:Meta Methods classWrapper = {name = “NSObject”, instance = nil} mt = {} mt.__call = function(table) table.instance = 0xFFFF; -- 初始化 end Setmetatable(classWrapper, mt) 主要用来做初始化 typedef struct _wax_instance_userdata { id instance; BOOL isClass; Class isSuper; BOOL actAsSuper; } wax_instance_userdata; 此处的初始化是指使用运行时方法创建类。
  26. 26. Hello Lua:Meta Methods classWrapper = {name = “NSObject”, instance = nil} mt = {} mt.__call = function(table) table.instance = 0xFFFF; -- 初始化 end Setmetatable(classWrapper, mt) 主要用来做初始化 typedef struct _wax_instance_userdata { id instance; BOOL isClass; Class isSuper; BOOL actAsSuper; } wax_instance_userdata; 此处的初始化是指使用运行时方法创建类。
  27. 27. Lua 与 ObjC 集成的原理 • Objective-C Runtime API: – <objc/runtime.h>, <objc/message.h> – objc_allocateClassPair – class_addIvar – class_addMethod – … • Lua 的 meta 特性: – UserData:C Struct – __index(lua_State *L) – __call(lua_State *L); – C Function Closure
  28. 28. Lua 与 ObjC 集成的原理 • 需要解决的两个问题: – 在 Lua 中生成 ObjC 的 Class • 利用 UserData,ObjC Runtime API – 将 Lua 的调用转换为 ObjC 的调用 • 利用 Lua 的 C Function Closure, NSInvocation * meta programming – meta data – 编译时的特性 – Common Lisp 的 s-expression – C++ 的 meta template programming – lex/yacc
  29. 29. wax 框架及其本身的一些问题 • https://github.com/probablycorey/wax/ • 设计目标:使用 Lua 开发应用 – ObjC 为 Lua 提供库 – 只提供单向的辅助函数:ObjC→Lua – 只提供一个 lua_State • 对 wax 做了部分修改 • 其他的一些库: – Lua-Objective-C-Bridge – LuaCocoa * 开源库的选择方法
  30. 30. Demos:初始化与释放 初始化的是 lua_State 单例: wax_start("SampleScript.lua", NULL); // TODO: wax_end(); 多例: lua_State *lv = fm_start("SampleScript.lua", NULL); // TODO: fm_end(lv);
  31. 31. Demos:从Lua中读取整型 Lua: count = 2 ObjC: // number lua_getglobal(L, "count"); int count = lua_tonumber(L, -1); NSLog(@"Count From Lua: %d", count); lua_pop(L, 1);
  32. 32. Demos:从Lua中读取字符串 Lua: msg = “hello everyone” ObjC: // string lua_getglobal(L, "msg"); const char *msg = lua_tostring(L, -1); NSLog(@"Msg From Lua: %s", msg); lua_pop(L, 1);
  33. 33. Demos:从Lua中读取ObjC变量 Lua: alertView = UIAlertView :initWithTitle_message_delegate_cancelButtonTitle_otherButtonTitles( nil, "Hello Lua!", nil, "确定", nil); ObjC: // objc var lua_getglobal(L, "alertView"); UIAlertView *alertView = fm_instance_getObject(L, -1); [alertView show]; lua_pop(L, 1);
  34. 34. Demos:调用Lua函数-1 Lua: -- Lua Functions function SayHello() print("hello lua!") end endObjC: //wax_printStack(_luaState); lua_getglobal(_luaState, "SayHello"); //wax_printStack(_luaState); wax_pcall(_luaState, 0, 0); //wax_printStack(_luaState); lua_pop(_luaState, 1); //wax_printStack(_luaState);
  35. 35. Demos:调用Lua函数-2 Lua: function SayHello2(msg) print(msg) end ObjC: lua_getglobal(_luaState, "SayHello2"); lua_pushstring(_luaState, "msg from objc"); wax_pcall(_luaState, 1, 0); lua_pop(_luaState, 1);
  36. 36. Demos:调用Lua函数-3 Lua: function SayHello3(msgDict) msg = msgDict["msg"] print(msg) end endObjC: lua_getglobal(_luaState, "SayHello3"); NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: @"hello lua from objc", @"msg", nil]; wax_fromInstance(_luaState, dict); wax_pcall(_luaState, 1, 0); lua_pop(_luaState, 1);
  37. 37. Demos:调用Lua函数-4 Lua: -- with object function SayHello4(obj) obj:sayHello(toobjc("hello from lua")) end ObjC: - (void)sayHello:(NSString *)msg { UIAlertView *alertView = [[[UIAlertView alloc] initWithTitle:@"Call from lua" message:msg delegate:nil cancelButtonTitle:@"Cancel" otherButtonTitles:nil] autorelease]; [alertView show]; } - (void)callLuaWithObject:(id)sender { lua_getglobal(_luaState, "SayHello4"); wax_fromInstance(_luaState, self); wax_pcall(_luaState, 1, 0); lua_pop(_luaState, 1); }
  38. 38. Demos:调用Lua函数-5 Lua: -- return string function SayHello5() return "raw string from lua" end ObjC: lua_getglobal(_luaState, "SayHello5"); wax_pcall(_luaState, 0, 1); const char *msg = lua_tostring(_luaState, -1); [self sayHello:[NSString stringWithUTF8String:msg]]; lua_pop(_luaState, 1);
  39. 39. Demos:调用Lua函数-6 Lua: -- return objc string function SayHello6() return toobjc("objc string from lua") end ObjC: lua_getglobal(_luaState, "SayHello6"); wax_pcall(_luaState, 0, 1); NSString *msg = (NSString *)fm_instance_getObject(_luaState, -1); [self sayHello:msg]; lua_pop(_luaState, 1);
  40. 40. Demos:调用C函数 C: static int SampleCFunction(lua_State *L) { const char *param = lua_tostring(L, -1); … return 0; } lua_pushcfunction(_luaState, SampleCFunction); lua_setglobal(_luaState, "showMsg"); Lua: function SayHello7() return showMsg("hi") end ObjC: lua_getglobal(_luaState, "SayHello7"); wax_pcall(_luaState, 0, 0); lua_pop(_luaState, 1);
  41. 41. 其他 • 胶水语言 • 多大的接口粒度是合适的? • 在业务领域中应用Lua的切入点
  42. 42. 讨论? 谢谢!

×