动态语言 & ios程序 - lua基础

经常有看到一些游戏可以不通过appstore而修改一些东西,比如增加功能。

这个其实就是通过下载脚本来实现的。常见的脚本就是js和lua吧。

个人对lua比较熟悉。

lua这货还是挺牛的,解释器非常小,速度也非常快,和C语言函数的交互也很容易。

集成lua到xcode工程

很容易,

1. 到lua官网,下载源代码,http://www.lua.org/download.html

2. 在要集成lua的工程里面,添加一个target,选择静态库。

3. 把lua源代码(.h, .c)拉到新建的静态库里面,编译。

4. 在目标工程里面,link刚编译出来的.a文件。如:

这样环境就算弄好了。

使用lua

先include几个lua的头文件。

//extern "C"
//{
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
//}

如果是c++环境,则需要把extern "C"打开。

准备Lua脚本文件

这里,就简单的创建一个资源。实际上这个脚步可以从服务器下载,保存在本地机器。

创建本地资源文件很简单,我这里就直接创建一个空的文件,命名为my.lua。

然后写入脚本:

这个脚本非常的简单,就是定义一个全局变量myname和一个函数lefthandcall。

在函数内部调用一个lhc的函数,返回。

调用lua函数

直接给出代码,看注释:

- (IBAction)testLua:(id)sender {
    l = luaL_newstate();  // 新建一个lua状态

    luaL_openlibs(l);  // 加载lua库

    NSString *scriptpath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"my.lua"];  // 读取资源文件里面的lua文件路径
    //    NSString* content = [NSString stringWithContentsOfFile:scriptpath encoding:NSUTF8StringEncoding error: nil];
    int iError = luaL_loadfile(l, scriptpath.UTF8String);  // 加载lua文件
    iError = lua_pcall(l, 0, 0, 0);  // 先执行一下,可以获取lua脚本的一些变量

    int iTop = lua_gettop(l);  // 获取栈顶元素的索引,这里应该是0,也就是栈还是空的。

    lua_getglobal(l, "myname");  // 获取lua里面的一个名字为myname的全局变量,这个全局变量的值会压栈

    iTop = lua_gettop(l);  // 所以这里应该是1, 栈顶索引时1,也就是只有一个元素。

    const char* p = lua_tostring(l, -1);  // 可以获取lua脚本里面的myname变量的值。
    printf("global variable value: %s", p);

    lua_pushcfunction(l, myTest);  // 把一个c语言函数压栈。

    iTop = lua_gettop(l);  // 现在应该是2

    lua_setglobal(l, "lhc");  // 把栈顶的myTest函数设置成lua环境里面的全局变量,名字为lhc,lua_setglobal函数有出栈功能。

    iTop = lua_gettop(l);  // 这个时候,应该是1,这个元素其实就是myname变量的值,可以再次尝试获取。

    p = lua_tostring(l, -1);

    lua_pop(l, 1);  // 从栈顶移除一个元素。

    iTop = lua_gettop(l);  // 应该是0

    lua_getglobal(l, "lefthandcall");  // 获取lua脚本里面的名字为lefthandcall的函数,压栈。
    iTop = lua_gettop(l);  // 应该是1
    lua_pushnumber(l, 15);  // 压入参数
    lua_pushnumber(l, 20);  // 压入参数

    iTop = lua_gettop(l);  // 栈顶索引是3,一个lua脚本的函数,2个参数。

    iError = lua_pcall(l, 2, 1, 0 );  // 调用lua函数,会把栈里面的lua函数和两个参数移除,然后把返回值压栈。

    iTop = lua_gettop(l);  // 3 - 3 + 1 = 1

    printf("ret: %s", lua_tostring(l, -1));  // 打印返回值。

    lua_pop(l, iTop);  // 清空栈。

    iTop = lua_gettop(l);  // 0

    lua_close(l);  // 关闭lua状态。
}

上面的代码主要做了这么几个事情:

1. 新建一个lua状态

2. 获取一个lua脚本里的全局变量。

3. 把一个C语言函数myTest压栈,并且设置成lua环境里面的一个全局函数。

4. 获取lua脚本的函数,并且压入相应的参数

5. 调用lua脚本函数。

mytest函数代码如下:

int myTest(lua_State* L)  // 这个函数会被脚本执行。
{
    // 先检测传入的2个参数是否为数值型
    if (!lua_isnumber(L, 1)){
        return lua_error(L);
    }
    if (!lua_isnumber(L, 2)){
        return lua_error(L);
    }

    double a = lua_tonumber(L, 1);
    double b = lua_tonumber(L, 2);
    a>b?lua_pushnumber(L, a):lua_pushnumber(L, b);  // 把2个参数里面大的值压栈,也就是返回值。

    root.myLabel.hidden = NO;  // 显示一个原来是隐藏的label。

    return 1;
}

基本上,整个过程就是:

1. iOS的按钮响应函数调用lua脚本函数lefthandcall

2. lua脚本函数lefthandcall调用lhc函数

3. lhc是lua环境里的一个全局函数,由#1设置。lhc的本身代码是C语言。也就是上面的myTest函数。

运行一下,就会得到2个结果:

1. myTest函数的返回值,也就是2个参入参数的大的值

2. myTest里面,把一个label给显示出来了。见下图,点击TestLua按钮上,会显示上面的label “Shown by Lua”

总结

在ios开发里面使用lua还是挺简单的,也很好用。上面的例子,我们显示了一个label,实际上可以做更多其他的事情。

比如,扩展一些简单的功能。

有了lua这种动态执行脚本,可以给我们的程序增加一些灵活性。有些时候,做一些功能的改动还是挺好的,可以省去再次审核,但是有时像appstore可能会因为集成了这类功能,而拒绝审核。但是不管怎么样,这总是给了我们一个比较好的小范围调整程序的方法。

当然,如果改动很大,那最好的办法还是发布一个新的app版本,不然lua会整的非常复杂。

附:

xcode 6, iOS sdk 8, lua 5.3

//
//  ViewController.m
//  TestLua
//
//  Created by Kevin on 15/3/3.
//  Copyright (c) 2015年 Kevin. All rights reserved.
//

#import "ViewController.h"

//extern "C"
//{
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
//}

lua_State *l;
ViewController* root;

int myTest(lua_State* L)  // 这个函数会被脚本执行。
{
    // 先检测传入的2个参数是否为数值型
    if (!lua_isnumber(L, 1)){
        return lua_error(L);
    }
    if (!lua_isnumber(L, 2)){
        return lua_error(L);
    }

    double a = lua_tonumber(L, 1);
    double b = lua_tonumber(L, 2);
    a>b?lua_pushnumber(L, a):lua_pushnumber(L, b);  // 把2个参数里面大的值压栈,也就是返回值。

    root.myLabel.hidden = NO;  // 显示一个原来是隐藏的label。

    return 1;
}

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // Do any additional setup after loading the view, typically from a nib.

    root = self;
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.

}

- (IBAction)testLua:(id)sender {
    l = luaL_newstate();  // 新建一个lua状态

    luaL_openlibs(l);  // 加载lua库

    NSString *scriptpath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"my.lua"];  // 读取资源文件里面的lua文件路径
    //    NSString* content = [NSString stringWithContentsOfFile:scriptpath encoding:NSUTF8StringEncoding error: nil];
    int iError = luaL_loadfile(l, scriptpath.UTF8String);  // 加载lua文件
    iError = lua_pcall(l, 0, 0, 0);  // 先执行一下,可以获取lua脚本的一些变量

    int iTop = lua_gettop(l);  // 获取栈顶元素的索引,这里应该是0,也就是栈还是空的。

    lua_getglobal(l, "myname");  // 获取lua里面的一个名字为myname的全局变量,这个全局变量的值会压栈

    iTop = lua_gettop(l);  // 所以这里应该是1, 栈顶索引时1,也就是只有一个元素。

    const char* p = lua_tostring(l, -1);  // 可以获取lua脚本里面的myname变量的值。
    printf("global variable value: %s", p);

    lua_pushcfunction(l, myTest);  // 把一个c语言函数压栈。

    iTop = lua_gettop(l);  // 现在应该是2

    lua_setglobal(l, "lhc");  // 把栈顶的myTest函数设置成lua环境里面的全局变量,名字为lhc,lua_setglobal函数有出栈功能。

    iTop = lua_gettop(l);  // 这个时候,应该是1,这个元素其实就是myname变量的值,可以再次尝试获取。

    p = lua_tostring(l, -1);

    lua_pop(l, 1);  // 从栈顶移除一个元素。

    iTop = lua_gettop(l);  // 应该是0

    lua_getglobal(l, "lefthandcall");  // 获取lua脚本里面的名字为lefthandcall的函数,压栈。
    iTop = lua_gettop(l);  // 应该是1
    lua_pushnumber(l, 15);  // 压入参数
    lua_pushnumber(l, 20);  // 压入参数

    iTop = lua_gettop(l);  // 栈顶索引是3,一个lua脚本的函数,2个参数。

    iError = lua_pcall(l, 2, 1, 0 );  // 调用lua函数,会把栈里面的lua函数和两个参数移除,然后把返回值压栈。

    iTop = lua_gettop(l);  // 3 - 3 + 1 = 1

    printf("ret: %s", lua_tostring(l, -1));  // 打印返回值。

    lua_pop(l, iTop);  // 清空栈。

    iTop = lua_gettop(l);  // 0

    lua_close(l);  // 关闭lua状态。
}
@end
时间: 2024-07-30 08:04:36

动态语言 & ios程序 - lua基础的相关文章

5月编程语言排行榜:动态语言的前世今生

TIOBE近日发布了2010年5月的编程语言排行榜,上期榜单C语言反超Java,本期C继续以18.186%的份额领跑,Java则位居第二.排名三到五位的依然是C++.PHP.VB,以下是本期编程语言排行榜前十名榜单: 更多榜单回顾,欢迎访问:51CTO编程语言排行榜 2010年5月编程语言排行榜榜单 仔细观察本期榜单的Top10,我们会发现其中半数是动态语言,它们是:PHP.Visual Basic.Python.Perl和JavaScript.今天我们就一起走进动态语言的前世今生.  前10名

动态语言/动态类型语言/静态类型语言

动态语言 指程序在运行时可以改变其结构:新的函数可以被引进,已有的函数可以被删除,即结构上的变化 如众所周知的ECMAScrip(JavaScript)便是一个动态语言 除此之外,Ruby.Python也都属于动态语言 C与C++则不属于动态语言 动态类型语言 指类型检查是在运行时做的 静态类型语言 分析 类型检查是在运行前判断(如编译阶段),如C#和java都是静态类型语言 静态类型语言为了达到多态,会采取一些类型鉴别手段,如继承.接口 而动态类型语言不需要,所以一般动态语言都会采用dynam

iOS 程序插件及功能动态更新思路

所用框架及语言 iOS客户端-Wax(开发愤怒的小鸟的连接Lua 和 Objc的框架),Lua,Objc, 服务端-Java(用于返回插件页面) 工具框架链接地址:Wax - https://github.com/probablycorey/wax  Netty - https://netty.io/  用做Http服务器,返回页面 由于Lua脚本语言,不需要编译即可运行,这点是我的这个思路可以执行的大前提,再加上苹果允许像Lua这样的脚本的存在,这一思路才能得以实现.个人感觉这一思路有点类似于

iOS开发系列--IOS程序开发概览ios基础

iOS开发系列--IOS程序开发概览 2014-08-04 19:42 by KenshinCui, 72273 阅读, 81 评论, 收藏,  编辑 概览 终于到了真正接触IOS应用程序的时刻了,之前我们花了很多时间去讨论C语言.ObjC等知识,对于很多朋友而言开发IOS第一天就想直接看到成果,看到可以运行的IOS程序.但是这里我想强调一下,前面的知识是你日后开发IOS的基础,没有那些知识你开发IOS会很痛苦,现在很多开发人员做开发都是一知半解,程序质量确实令人担忧,所以还是希望大家能够熟练掌

iOS开发UI基础—简单的浏览器查看程序

iOS开发UI基础-简单的浏览器查看程序 一.程序实现要求 1.要求 2. 界面分析 (1) 需要读取或修改属性的控件需要设置属性 序号标签 图片 图片描述 左边按钮 右边按钮 (2) 需要监听响应事件的对象,需要添加监听方法 左边按钮 右边按钮 二.实现基本功能的程序 1 // 2 // YYViewController.m 3 // 03-图片浏览器初步 4 // 5 // Created by apple on 14-5-21. 6 // Copyright (c) 2014年 itcas

python 基础学习之动态语言初识

初衷 C/C++/Java语言都是静态语言,而python是动态语言,那就先从这个点出发,来学习python... 基本概念 静态语言(强类型语言) 静态语言是在编译时变量的数据类型即可确定的语言,多数静态类型语言要求在使用变量之前必须声明数据类型. 例如:C++.Java.Delphi.C#等. 动态语言(弱类型语言) 动态语言是在运行时确定数据类型的语言.变量使用之前不需要类型声明,通常变量的类型是被赋值的那个值的类型. 例如PHP/ASP/Ruby/Python/Perl/ABAP/SQL

Lua语言自学之01.基础概念的理解

编程不只是这么简单,它的思维是理性的编程思维,操纵机器干事本来就不是一件简单的事,要干什么,该怎么做,怎么做得才好. 脚本的概念在程序中十分重要,在游戏开发领域,它更是决定性的.脚本语言让程序员可以区分游戏开发的"硬核部分"和"软核部分"."硬核部分"一般对计算机性能要求很高,在开发过程中变更较少,重要性很高.图形引擎和人工智能模块是其中的代表.这些模块最适合使用C或者C++这样的语言开发,可以提供更好的性能."软体部分"控制

Javascript基础练习之实现C语言经典程序题

前言: 最近在学习Javascript语言,看到网上很多都是在介绍Javascript如何解决网页上问题的代码,所以想另辟蹊径,用Javascript代码来实现C语言经典程序题.当然,这些C语言程序题也是比较简单,主要想通过Javascript语言实现,起到语法练习作用,也想来对比一下C语言和Javascript语言实现的相同点和不同点,从而巩固记忆,加强学习效果!!! 一.C语言经典程序题1 1. 题目描述: 马克思的手稿中有这样一道有趣的数学题:有30个人,其中有男人,女人,小孩.他们在一家

JSPatch – 动态更新iOS APP

博文转载至 http://blog.cnbang.net/works/2767/ JSPatch是最近业余做的项目,只需在项目中引入极小的引擎,就可以使用JavaScript调用任何Objective-C的原生接口,获得脚本语言的能力:动态更新APP,替换项目原生代码修复bug. 用途 是否有过这样的经历:新版本上线后发现有个严重的bug,可能会导致crash率激增,可能会使网络请求无法发出,这时能做的只是赶紧修复bug然后提交等待漫长的AppStore审核,再盼望用户快点升级,付出巨大的人力和