经常有看到一些游戏可以不通过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);  // 现在应该是2lua_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);  // 应该是0lua_getglobal(l, "lefthandcall");  // 获取lua脚本里面的名字为lefthandcall的函数,压栈。iTop = lua_gettop(l);  // 应该是1lua_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 = 1printf("ret: %s", lua_tostring(l, -1));  // 打印返回值。lua_pop(l, iTop);  // 清空栈。iTop = lua_gettop(l);  // 0lua_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);  // 现在应该是2lua_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);  // 应该是0lua_getglobal(l, "lefthandcall");  // 获取lua脚本里面的名字为lefthandcall的函数,压栈。iTop = lua_gettop(l);  // 应该是1lua_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 = 1printf("ret: %s", lua_tostring(l, -1));  // 打印返回值。lua_pop(l, iTop);  // 清空栈。iTop = lua_gettop(l);  // 0lua_close(l);  // 关闭lua状态。
}
@end

动态语言 ios程序 - lua基础相关推荐

  1. lua语言和python_[动态语言]python和lua中的三元操作符and-or

    在这两种语言中,表达式a and b的返回值不是true或false,而是a/b当中非真的值,而表示a or b返回的是a/b当中为真的那个. 因此,要想模拟C/C++中的三元操作符c ? a : b ...

  2. 用c语言写代码_如何避免用动态语言的思维写Go代码

    由于招聘市场上Go工程师的供给量不足,所以在招人的时候我们招了不少愿意转型用Go语言进行开发的PHP工程师,不过虽说换了个语言,在他们代码的时候还是能发现很多PHP的影子.if语句后面非要带括号这种问 ...

  3. 如何避免用动态语言的思维写Go代码

    转载地址:https://mp.weixin.qq.com/s/xNmhk_ZI38MgJt9rRZz7LA 由于招聘市场上Go工程师的供给量不足,所以在招人的时候我们招了不少愿意转型用Go语言进行开 ...

  4. c语言延时系统,基于VB的单片机C语言延时程序各参数计算系统

    仪器仪表用户 doi:10.3969/j.issn.1671-1041.2011.04.013 □科研设计成果□ 基于VB的单片机C语言延时程序各参数计算系统 刘 1 锋,林 奕 2 (1.武汉理工大 ...

  5. Silverlight 2教程(四):Chiron.exe:Silverlight 2打包和动态语言部署工具

    VS在编译时Silverlight 2的应用程序时,会先将cs等文件进行编译成dll,然后会调用Chiron.exe这个打包工具打包成.xap文件.也可以使用它进行动态语言无打包部署.Chiron.e ...

  6. Silverlight 2学习教程(四):Chiron.exe:Silverlight 2打包和动态语言部署工具

    VS在编译时Silverlight 2的应用程序时,会先将cs等文件进行编译成dll,然后会调用Chiron.exe这个打包工具打包成.xap文件.也可以使用它进行动态语言无打包部署.Chiron.e ...

  7. android jnl的mk文件,动态语言与静态语言

    动态语言也称为脚本语言,是介于标签语言(如HTML,XSLT,VML)和静态语言(如C++.C#.Java,也称编译语言)之间的语言.JavaScript.PHP.Perl.Ruby等都是动态语言.动 ...

  8. python中动态语言静态语言的定义_作为程序开发,你所需要知道的编译型与解释型、动态语言与静态语言、强类型语言与弱类型语言的概念以及区别...

    作为程序开发,你所需要知道的编译型与解释型.动态语言与静态语言.强类型语言与弱类型语言的概念以及区别! 在各式各样的开发过程当中,我相信各位开发小伙伴在开发过程中并没有太关注什么是解释性语言和编译性语 ...

  9. IOS 程序插件及功能动态更新思路┊

    http://www.cocoachina.com/bbs/read.php?tid=129723&keyword=%B2%E5%BC%FE 带图片版 CSDN路径-- http://blog ...

最新文章

  1. Cissp-【第3章 安全工程】-2021-2-20(248页-268页)
  2. 怎么查看linux挂载的硬盘,如何查看Linux服务器已挂载的硬盘
  3. 【卷积神经网络】ResNet翻译详解
  4. Junit 测试时内存溢出解决办法
  5. 《微信公众平台入门到精通》,青龙老贼,详情版本
  6. 项目管理---SVN,Subversion的安装,客户端和服务端
  7. HDU2024 C语言合法标识符【文本处理】
  8. 自定义http报头_http协议报头详解HTTP协议结构
  9. 五子棋初步以及对五子棋的局面估值
  10. Windows 11 右键菜单反应慢解决
  11. linux ftp 测网速,武汉电信使用FTP测试网速
  12. Dfinity(icp)参考命令及规范-7
  13. zabbix如何自定义一个监控项对web网站进行存活监控和报警?
  14. ios开发——图层的新建属性设置和添加
  15. android设置应用字体大小,在Android应用程序改变的TextView的字体大小从原始设置更改字体大小(Font size...
  16. 【每日蓝桥】16、一三年省赛Java组真题“幸运数”
  17. 三色过人脸脚本_格灵深瞳算法团队获得NIST人脸识别竞赛全球第一
  18. 40G/100G万兆交换机如何选择?
  19. webp格式如何转成png?
  20. 天黑请闭眼服务器维护中,天黑请闭眼!

热门文章

  1. ios keychain 不被清理_【良心好用】推荐一些iOS,安卓不可错过的APP
  2. 10K负温度系数热敏电阻(NTC)温度与阻值对应关系表
  3. 基于SPRINGBOOT-创意产品众筹平台
  4. 计算机系统崩溃代码,这12行代码分分钟让你电脑崩溃手机重启
  5. 3分钟搞懂Vue整合Echarts实现可视化界面
  6. 河畔林语html操作,项目河畔林语.rar
  7. 浅谈基于SDL的2D纵版弹幕射击游戏相关经验心得
  8. 用PHP写了个校园里卖二手书和二手物品的小网站
  9. C#开发BIMFACE系列9 服务端API之获取应用支持的文件类型
  10. Win10 IIS Web 配置