动用LuaScriptCore来让Lua与iOS进行交互,读取Lua配置文件落到实处案例

by admin on 2019年8月22日

使用C++读取Lua配置文件动用LuaScriptCore来让Lua与iOS进行交互,读取Lua配置文件落到实处案例。落到实处案例是本文要介绍的剧情,首即便来询问并学习一下lua配备文件的利用,本文内容器重是以代码来促成,具体内容来看本文详解。

前言

正文基于 Lua 5.3.

Lua
是二个轻量级脚本语言,常用来放置其余语言作为补充。关于更加的多Lua本身的难题不在本文钻探范围之内。
在 Android 中放到 Lua 优点比相当多,借助 Lua
脚本语言的优势,能够轻易完结动态逻辑调控,应用能够每一天从服务器读取最新
Lua 脚本文件,在不立异应用的情景下修改程序逻辑。
心痛 Lua 官方只提供了 C API ,而 Android 重要运用 JAVA
作为支付语言。大家得以凭借 JNI 来直接完毕在 Android 中放到 Lua 。

想必有部分人对lua并非太熟稔,它实质上跟JavaScript、Ruby、Python等同为脚本语言。可是越来越轻量,尤其从简,未有别的多余的效劳。那也使得它能够依赖本人的急需来扩充定制。举例作为利用的布署文件,又恐怕是游戏的本子引擎等等。

小说来源:

//LuaEx.h文件   #pragma once  #include <Windows.h> extern "C"  {  #include "lua/lua.h"  #include "lua/lualib.h"  #include "lua/lauxlib.h"  };   class LuaEx  {  public:  LuaEx(void);  ~LuaEx(void);  bool LoadFile(LPCSTR str); //载入lua文件  LPSTR LoadString(LPCSTR str); //读取字符串  int LoadInteger(LPCSTR str); //读取整形  double LoadDouble(LPCSTR str); //读取浮点型  bool LoadBoolean(LPCSTR str); //读取布尔型   private:  lua_State *L; //lua指针  };   //LuaEx.cpp文件   #include ".\luaex.h"  #pragma comment(lib, ".\\lua\\lua.lib")   LuaEx::LuaEx(void)  {  L = lua_open();  luaL_openlibs(L);  }   LuaEx::~LuaEx(void)  {  lua_close(L);  }   bool LuaEx::LoadFile(LPCSTR str)  {  if(luaL_dofile(L, str))  {  return false;  }  return true;  }   LPSTR LuaEx::LoadString(LPCSTR str)  {  lua_getglobal(L, str);  if (lua_isstring(L, -1))  {  return (LPSTR)lua_tostring(L, -1);  }  return NULL;  }   int LuaEx::LoadInteger(LPCSTR str)  {  lua_getglobal(L, str);  if (lua_isnumber(L, -1))  {  return (int)lua_tointeger(L, -1);  }  return NULL;  }   double LuaEx::LoadDouble(LPCSTR str)  {  lua_getglobal(L, str);  if (lua_isnumber(L, -1))  {  return (double)lua_tonumber(L, -1);  }  return 0.0;  }   bool LuaEx::LoadBoolean(LPCSTR str)  {  lua_getglobal(L, str);  if (lua_isboolean(L, -1))  {  return (bool)lua_toboolean(L, -1);  }  return false;  } 

准备

友好完结 JNI 是一件很棘手的事情,还好有人曾经造好了轮子叫做 Luajava
,何况又有人依据 Luajava 做了 Android 专项使用库。网络流传最广的是
Androlua
,然则小编曾经积年累月不维护了,对 Lua
的支撑依然停留在5.1何况有局地bug,有人Fork了这么些类型,并将其履新至 Lua
5.3 :New
Androlua
,可是这几个项目也存在部分主题材料,作者修复了一晃可是小编并不曾处理作者的 pull
request
,各位能够直接选取本人修复优化后的:Android-Lua.

在修复bug的同有时间,笔者也增添了一部分普通话注释,缩短第贰遍接触 Lua C API
朋友们的求学纪念花费。

是因为最终必要调用 Lua C API,所以请先配备 NDK 开辟景况。在 Android Studio
中开采 SDK Manager,切换成 SDK Tools
标签页,勾选CMakeLLDBNDK下载安装之。

home88一必发 1

NDK环境

是因为它的轻量,因而它要写越来越多的代码来贯彻协调所需的效率,临时候还须求运用Lua提供的C
Api来拓宽功效扩充,对于运动道具来讲更是如此,举例:访问定位、照相机等等。

1

在要选取布置文件的地方实例化八个LuaEx类就足以了。

导入工程

单独想完毕 Android Lua 相互调用,不敬服具体进程的,能够一向抬高正视:
implementation 'cc.chenhe:android-lua:1.0.2'
然后前面包车型客车导入部分能够跳过了。

Clone github 项目到本地并用 Android Studio
展开。大概能够看出下图目录结构。(由于前期更新,结构不明确大同小异)

home88一必发 2

目录结构

其中 androidlua是库,app是demo工程。库中,lua下是 Lua
解释引擎,luajava是 JNI 的关于代码。*.mk
文件是NDK配置文件,详细情形请参谋Google NDK
文档。

你能够将 androidluaModule 导入本身工程作为依赖库使用。

并且Lua的C
Api相对来说不轻巧驾驭和调控,必要投入一定的时辰去学学和堆成堆那方面包车型大巴经历。而LuaScriptCore不怕为了消除那个标题而诞生,他简化了扩展Lua的难度,让开采者能够透过本身熟谙的语言来扩张Lua,完美化解Lua与原生代码之间的报道难点。

前言:

本文来源:

开涛的博客—群众号:kaitao-1234567,长久以来的干货分享()


组成在类型中的实际用法边学边用,并把品种在那之中用到的一对代码和走过的一对坑在底下的篇章中另加表达,一同念书。


本文指标是上学Nginx+Lua开垦,对于Nginx基本知识可以参谋如下小说:

Nginx入门

nginx启动、关闭、重启

agentzh 的 Nginx 教程

Nginx+Lua入门

nginx 配置指令的实行顺序

nginx与lua的实践顺序和步子表达

Tengine的Nginx开辟从入门到领会

官方文书档案

Lua入门

Lua简明教程

lua在线lua学习课程

Lua 5.1 参照他事他说加以考察手册

Lua5.3 仿效手册

先调用LoadFile载入文件,参数为文件路线。文件格式能够依据如下格局:

Lua API 知识普遍

那会儿大家早已足以在 Android 与 Lua
直接互动调用了。但是在上马在此之前,还要学习下 Lua C API
的有关东西,因为那是与 Lua 交互的根底。

Lua 与 C
凭借贰个虚拟的栈来达成数据调换。富含变量、函数、参数、再次来到值等在内的100%数据,都要放入栈中来分享。为了调用方便,这几个栈实际不是从严服从栈的法则。从索引来看,栈底索引为1,往上种种递增。而栈顶索引是-1,往下相继递减。由此,正负索引都以官方的,但是0不得以。下边是栈的暗暗提示图:

home88一必发 3

Lua 栈

目前的LuaScriptCore本子为1.2.1,它协理iOS、Android、OSX平台,最新版本中还投入了对Unity3D的支撑。日后说不定会加盟越来越多的阳台的辅助,让其在各种平台下都能够越发低价地强大和操作Lua。上边作者来举八个例证,便是Lua作为iOS应用的配置文件,让视图能够依据配置文件钦点的颜色,来改换视图的背景颜色:

一丶Nginx Lua API

和一般的Web Server类似,大家要求接受必要、管理并出口响应。

对于请求我们需要获取如请求参数、请求头、Body体等信息;

对于处理就是调用相应的Lua代码即可;

对于输出响应需要进行响应状态码、响应头和响应内容体的输出。

之所以大家从如上多少个点出发就可以。

title = "游戏" width = 640 height = 480 isWindowed = true;  useSound = false;  hideMouse = false; 

动用LuaScriptCore来让Lua与iOS进行交互,读取Lua配置文件落到实处案例。常用 Lua C API 介绍

Lua 提供了汪洋的 C API,与另外语言的相互完全依据这几个API,下边包车型地铁基础教程中本文仲介绍多少个基础的,具体可以查阅Lua
官方手册

那一个函数均由 Lua 提供,在 Luajava 中被封装在 LuaState 类下。

  • 先是大家先到Github上下载LuaScriptCore。

  • 根据LuaScriptCore上的iOS集成文书档案将其集成到品种中。

  • 下一场在ViewController导入头文件”LuaScriptCore.h”,并在viewDidLoad方法中对LuaScriptCore进行开首化,如上边所示:

1丶接收央浼

(1)、example.conf配置文件

location ~ /lua_request/(\d+)/(\d+) {  
    #设置nginx变量  
    set $a $1;   
    set $b $host;  
    default_type "text/html";  
    #nginx内容处理  
    content_by_lua_file /usr/example/lua/test_request.lua;  
    #内容体处理完成后调用  
    echo_after_body "ngx.var.b $b";  
} 

在此付出一个其实的例证:

location /center { 
    proxy_pass http://127.0.0.1:8011/center;
}

location /center_install { 
    proxy_pass http://127.0.0.1:8012/center_install;
}

location /center_install/componentPackage/uploadPackage{
    content_by_lua_file upload_package.lua;
}

location /center_monitor { 
    proxy_pass http://127.0.0.1:8013/center_monitor;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
}

(2)、test_request.lua

本着上面的lua脚本并非单独的lua脚本,而是和Nginx集成之后的蓄意的局地语法,即下边包车型的士lua脚本用lua的IDE是不可能直接运营的,可是一直能够用lua的IDE运维的lua脚本是足以在Nginx中合拢的lua境遇中运维的。

正如方法管理一般的呼吁基本够用了。别的在读取post内容体时依据实情设置client_body_buffer_size和client_max_body_size来确定保障内容在内部存款和储蓄器实际不是在文件中。

ngx.var :nginx变量,假诺要赋值如ngx.var.b =
2,此变量必得提前注明;别的对于nginx
location中央银行使正则捕获的捕获组能够行使ngx.var[捕获组数字]获取;

ngx.req.get_headers:获取央求头,默许只得到前100,假若想要获取所以能够调用

ngx.req.get_headers(0):获取带中写道的呼吁头时请使用如headers.user_agent这种办法;假使三个央求头有七个值,则赶回的是table;

ngx.req.get_uri_args:获取url诉求参数,其用法和get_headers类似;

ngx.req.get_post_args:获取post乞请内容体,其用法和get_headers类似,然则必需超前调用

ngx.req.read_body():来读取body体(也能够选用在nginx配置文件使用lua_need_request_body
on;开启读取body体,但是官方不引入);

ngx.req.raw_header:未深入分析的伏乞头字符串;

ngx.req.get_body_data:为分析的伸手body体内容字符串。

如上海艺术剧场术管理一般的呼吁基本够用了。其他在读取post内容体时依据真实处境设置client_body_buffer_size和client_max_body_size来担保内容在内存并非在文件中。下边给出多少个上述办法事必躬亲:

--nginx变量  
local var = ngx.var  
ngx.say("ngx.var.a : ", var.a, "<br/>")  
ngx.say("ngx.var.b : ", var.b, "<br/>")  
ngx.say("ngx.var[2] : ", var[2], "<br/>")  
ngx.var.b = 2;  

ngx.say("<br/>")  

--请求头  
local headers = ngx.req.get_headers()  
ngx.say("headers begin", "<br/>")  
ngx.say("Host : ", headers["Host"], "<br/>")  
ngx.say("user-agent : ", headers["user-agent"], "<br/>")  
ngx.say("user-agent : ", headers.user_agent, "<br/>")  
for k,v in pairs(headers) do  
    if type(v) == "table" then  
        ngx.say(k, " : ", table.concat(v, ","), "<br/>")  
    else  
        ngx.say(k, " : ", v, "<br/>")  
    end  
end  
ngx.say("headers end", "<br/>")  
ngx.say("<br/>")  

--get请求uri参数  
ngx.say("uri args begin", "<br/>")  
local uri_args = ngx.req.get_uri_args()  
for k, v in pairs(uri_args) do  
    if type(v) == "table" then  
        ngx.say(k, " : ", table.concat(v, ", "), "<br/>")  
    else  
        ngx.say(k, ": ", v, "<br/>")  
    end  
end  
ngx.say("uri args end", "<br/>")  
ngx.say("<br/>")  

--post请求参数  
ngx.req.read_body()  
ngx.say("post args begin", "<br/>")  
local post_args = ngx.req.get_post_args()  
for k, v in pairs(post_args) do  
    if type(v) == "table" then  
        ngx.say(k, " : ", table.concat(v, ", "), "<br/>")  
    else  
        ngx.say(k, ": ", v, "<br/>")  
    end  
end  
ngx.say("post args end", "<br/>")  
ngx.say("<br/>")  

--请求的http协议版本  
ngx.say("ngx.req.http_version : ", ngx.req.http_version(), "<br/>")  
--请求方法  
ngx.say("ngx.req.get_method : ", ngx.req.get_method(), "<br/>")  
--原始的请求头内容  
ngx.say("ngx.req.raw_header : ",  ngx.req.raw_header(), "<br/>")  
--请求的body内容体  
ngx.say("ngx.req.get_body_data() : ", ngx.req.get_body_data(), "<br/>")  
ngx.say("<br/>")  

选拔如下脚本测验

wget --post-data 'a=1&b=2' 'http://127.0.0.1/lua_request/1/2?a=3&b=4' -O -  

末尾分号可加可不加,正是写三个lua脚本,可是只含有变量不分包方法。

luaL_openlibs

加载 Lua 标准库,一般须求调用一下。

2丶响应输出

(1.1)丶example.conf配置文件

location /lua_response_1 {  
    default_type "text/html";  
    content_by_lua_file /usr/example/lua/test_response_1.lua;  
}  

(1.2)丶test_response_1.lua

--写响应头  
ngx.header.a = "1"  
--多个响应头可以使用table  
ngx.header.b = {"2", "3"}  
--输出响应  
ngx.say("a", "b", "<br/>")  
ngx.print("c", "d", "<br/>")  
--200状态码退出  
return ngx.exit(200)

ngx.header:输出响应头;

ngx.print:输出响应内容体;

ngx.say:通ngx.print,不过会最后输出三个换行符;

ngx.exit:钦命状态码退出。

(2.1)example.conf配置文件

location /lua_response_2 {  
    default_type "text/html";  
    content_by_lua_file /usr/example/lua/test_response_2.lua;  
}  

(2.2)test_response_2.lua

ngx.redirect("http://jd.com", 302)  

ngx.redirect:重定向;

ngx.status=状态码,设置响应的状态码;ngx.resp.get_headers()获取设置的响应状态码;ngx.send_headers()发送响应状态码,当调用ngx.say/ngx.print时自动发送响应状态码;能够通过ngx.headers_sent=true剖断是或不是发送了响应状态码。

自此就能够读取在那之中内容了。比如

luaL_dostring

施行一段 Lua 脚本。

#import "ViewController.h"
#import "LuaScriptCore.h"

@interface ViewController ()

@property (nonatomic, strong) LSCContext *context;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.context = [[LSCContext alloc] init];
}

@end

3丶其他API

1、example.conf配置文件

location /lua_other {  
    default_type "text/html";  
    content_by_lua_file /usr/example/lua/test_other.lua;  
}  

2、test_other.lua

--未经解码的请求uri  
local request_uri = ngx.var.request_uri;  
ngx.say("request_uri : ", request_uri, "<br/>");  
--解码  
ngx.say("decode request_uri : ", ngx.unescape_uri(request_uri), "<br/>");  
--MD5  
ngx.say("ngx.md5 : ", ngx.md5("123"), "<br/>")  
--http time  
ngx.say("ngx.http_time : ", ngx.http_time(ngx.time()), "<br/>")  

ngx.escape_uri/ngx.unescape_uri : uri编码解码;

ngx.encode_args/ngx.decode_args:参数编码解码;

ngx.encode_base64/ngx.decode_base64:BASE64编码解码;

ngx.re.match:nginx正则表明式相配;

更多Nginx Lua API请参考

LoadString("title"); //表示载入变量名为title的变量的值。 

luaL_dofile

执行给定文件中的 Lua 脚本。

  • 增加一个叫作config.lua的布局文件,并在上头加多二个叫backgroundColor的变量,并开始化为革命,如:

4丶Nginx全局内存

使用过如Java的情人恐怕掌握如Ehcache等这种进度内本土缓存,Nginx是叁个Master进度三个Worker进程的劳作方法,因而咱们或然要求在五个Worker进程中国共产党享数据,那么此时就能够运用ngx.shared.DICT来贯彻全局内部存款和储蓄器分享。

(1)、首先在nginx.conf的http部分分配内部存款和储蓄器大小

#共享全局变量,在所有worker间共享  
lua_shared_dict shared_data 1m;  

(2)、example.conf配置文件

location /lua_shared_dict {  
    default_type "text/html";  
    content_by_lua_file /usr/example/lua/test_lua_shared_dict.lua;  
}  

(3)、 test_lua_shared_dict.lua

--1、获取全局共享内存变量  
local shared_data = ngx.shared.shared_data  

--2、获取字典值  
local i = shared_data:get("i")  
if not i then  
    i = 1  
    --3、惰性赋值  
    shared_data:set("i", i)  
    ngx.say("lazy set i ", i, "<br/>")  
end  
--递增  
i = shared_data:incr("i", 1)  
ngx.say("i=", i, "<br/>")  

更多API请参考。

到此基本的Nginx Lua
API就学完了,对于伏乞管理和出口响应如上介绍的API完全够用了,越来越多API请参见官方文档。


本类中颇具函数的参数都以字符串。

lua_dump

收获当前栈的从头到尾的经过。
java 中对应函数是dumpStack()home88一必发,,再次回到String,能够直接出口,便于调节和测量试验。

增加lua配置文件

二丶Nginx Lua模块指令

Nginx共十三个管理阶段,而相应的拍卖阶段是能够做插入式管理,就能够插拔式架构;别的指令能够在http、server、server
if、location、location if多少个范围拓宽示公布署:

home88一必发 4

更详尽的演说请参谋。如上指令比很多并不经常用,因而大家只拿里面包车型客车一部分做示范。

小结:关于C++读取Lua配置文件实现案例的剧情介绍完了,希望由此本文的读书能对您全数帮衬!

lua_pushXXX

将各类别型的数目压入栈,以便今后使用。

  • 然后在viewDidLoad方法中动用LSCContext来施行该脚本,如:

1丶init_by_lua

历次Nginx重新加载配置时实行,能够用它来形成都部队分耗费时间模块的加载,或许开首化一些大局配置;在Master进度成立Worker进程时,此命令中加载的全局变量会开展Copy-OnWrite,即会复制到全体全局变量到Worker进程。

(1)丶nginx.conf配置文件中的http部分加多如下代码

#共享全局变量,在所有worker间共享  
lua_shared_dict shared_data 1m;  

init_by_lua_file /usr/example/lua/init.lua; 

(2)、init.lua

--初始化耗时的模块  
local redis = require 'resty.redis'  
local cjson = require 'cjson'  

--全局变量,不推荐  
count = 1  

--共享全局内存  
local shared_data = ngx.shared.shared_data  
shared_data:set("count", 1)  

(3)、test.lua

count = count + 1  
ngx.say("global variable : ", count)  
local shared_data = ngx.shared.shared_data  
ngx.say(", shared memory : ", shared_data:get("count"))  
shared_data:incr("count", 1)  
ngx.say("hello world")  

(4)、演示

访问如
会开掘全局变量一向不改变,而分享内部存款和储蓄器一贯递增

global variable : 2 ,

shared memory : 8 

hello world 

其他注意早晚在生养意况开启lua_code_cache,不然每一个乞请都会创制Lua
VM实例。

C++ 读取 Lua配置文件
达成案例是本文要介绍的内容,主借使来打听并学习一下 lua 的 配置文件
的应用,本文内容根本是以代码来促成…

lua_toXXX

将栈中钦命索引处的值以xxx类型收取。

2丶init_worker_by_lua

用于运营一些定期任务,举个例子心跳检查,定时拉取服务器配置等等;此处的天职是跟Worker进程数量有涉嫌的,举例有2个Worker进度那么就能运转四个精光平等的定时任务。

(1)、nginx.conf配置文件中的http部分增加如下代码

init_worker_by_lua_file /usr/example/lua/init_worker.lua;  

(2)、init_worker.lua

local count = 0  
local delayInSeconds = 3  
local heartbeatCheck = nil  

heartbeatCheck = function(args)  
   count = count + 1  
   ngx.log(ngx.ERR, "do check ", count)  

   local ok, err = ngx.timer.at(delayInSeconds, heartbeatCheck)  

   if not ok then  
      ngx.log(ngx.ERR, "failed to startup heartbeart worker...", err)  
   end  
end  

heartbeatCheck() 

ngx.timer.at:延时调用相应的回调方法;ngx.timer.at(秒单位延时,回调函数,回调函数的参数列表);可以将延时设置为0即获得一个登时实行的职务,职责不会在现阶段乞请中推行不会阻塞当前乞请,而是在壹个轻量级线程中实践。

另外依据实际景况设置如下指令

lua_max_pending_timers 1024; #最大等待任务数

lua_max_running_timers 256; #最大並且运维任务数

lua_getglobal

获得 Lua 中的全局变量(包涵函数),并压入栈顶,以便以后选择。
参数就是要获得的变量的名字。

[self.context evalScriptFromFile:@"config.lua"];

3丶set_by_lua

设置nginx变量,大家用的set指令固然同盟if指令也很难完成担当的赋值逻辑;

(1.1)、example.conf配置文件

location /lua_set_1 {  
    default_type "text/html";  
    set_by_lua_file $num /usr/example/lua/test_set_1.lua;  
    echo $num;  
}  

set_by_lua_file:语法set_by_lua_file $var lua_file arg1 arg2…;
在lua代码中能够达成全数复杂的逻辑,不过要实行进度非常的慢,不要阻塞;

(1.2)、test_set_1.lua

local uri_args = ngx.req.get_uri_args()  
local i = uri_args["i"] or 0  
local j = uri_args["j"] or 0  

return i + j 

获得恳求参数进行相加然后回来。

访问如打开测量检验。
假若大家用纯set指令是无力回天完成的。

再举个实际例子,我们实际上中国人民解放军海军事工业程大学业作时常常涉及到网站改版,一时候需求新老并存,大概切一部分流量到新版

(2.1)、首先在example.conf中应用map指令来映射host到钦点nginx变量,方便大家测验

############ 测试时使用的动态请求  
map $host $item_dynamic {  
    default                     "0";  
    item2014.jd.com            "1";  
}  

如绑定hosts

192.168.1.2 item.jd.com;

192.168.1.2 item2014.jd.com;

这时候大家想拜望item二零一四.jd.com时访谈新版,那么我们能够差相当少的行使如

if ($item_dynamic = "1") {  
   proxy_pass http://new;  
}  
proxy_pass http://old;  

而是大家想把商品编号为为8位(举例品类为图书的)未有改版达成,需求遵从相应准绳跳转到老版,不过任何的到新版;即便应用if指令能落到实处,可是相比费力,基本必要如此

set jump "0";  
if($item_dynamic = "1") {  
    set $jump "1";  
}  
if(uri ~ "^/6[0-9]{7}.html") {  
   set $jump "${jump}2";  
}  
#非强制访问新版,且访问指定范围的商品  
if (jump == "02") {  
   proxy_pass http://old;  
}  
proxy_pass http://new;  

以上法则仍旧相比轻便的,纵然提到到更复杂的多种if/else或嵌套if/else完毕起来就更加难受了,恐怕必要到后端去做了;此时大家就能够借助lua了:

set_by_lua $to_book '  
     local ngx_match = ngx.re.match  
     local var = ngx.var  
     local skuId = var.skuId  
     local r = var.item_dynamic ~= "1" and ngx.re.match(skuId, "^[0-9]{8}$")  
     if r then return "1" else return "0" end;  
';  
set_by_lua $to_mvd '  
     local ngx_match = ngx.re.match  
     local var = ngx.var  
     local skuId = var.skuId  
     local r = var.item_dynamic ~= "1" and ngx.re.match(skuId, "^[0-9]{9}$")  
     if r then return "1" else return "0" end;  
';  
#自营图书  
if ($to_book) {  
    proxy_pass http://127.0.0.1/old_book/$skuId.html;  
}  
#自营音像  
if ($to_mvd) {  
    proxy_pass http://127.0.0.1/old_mvd/$skuId.html;  
}  
#默认  
proxy_pass http://127.0.0.1/proxy/$skuId.html;  

lua_getfield

赢得 Lua 中 某一 table 的因素,并压入栈顶。
首先个参数是 table 在栈中的索引,第贰个参数是要获得元素的 key.

  • 再通过LSContext获取lua里面包车型大巴背景颜色变量backgroundColor并退换ViewController的view的背景颜色,如:

4丶rewrite_by_lua

实践内部U科雷傲L重写大概外界重定向,规范的如伪静态化的ULacrosseL重写。其默许施行在rewrite管理阶段的末段。

(1.1)、example.conf配置文件

location /lua_rewrite_1 {  
    default_type "text/html";  
    rewrite_by_lua_file /usr/example/lua/test_rewrite_1.lua;  
    echo "no rewrite";  
}  

(1.2)丶test_rewrite_1.lua

if ngx.req.get_uri_args()["jump"] == "1" then  
   return ngx.redirect("http://www.jd.com?jump=1", 302)  
end  

当大家央求时意识并未跳转,而央求时意识跳转到京东首页了。
此处要求3056%02跳转遵照自个儿须求定义。

(2.1)、example.conf配置文件

location /lua_rewrite_2 {  
    default_type "text/html";  
    rewrite_by_lua_file /usr/example/lua/test_rewrite_2.lua;  
    echo "rewrite2 uri : $uri, a : $arg_a";  
}  

(2.2)、test_rewrite_2.lua

if ngx.req.get_uri_args()["jump"] == "1" then  
   ngx.req.set_uri("/lua_rewrite_3", false);  
   ngx.req.set_uri("/lua_rewrite_4", false);  
   ngx.req.set_uri_args({a = 1, b = 2});  
end  

ngx.req.set_uri(uri, false):

能够内部重写uri(能够带参数),等价于 rewrite ^ /lua_rewrite_3;
通过相称if/else可以完毕 rewrite^ /lua_rewrite_3
break;这种意义;此处两个都是location内部url重写,不会重新发起新的location匹配;

ngx.req.set_uri_args:

重写须求参数,能够是字符串(a=1&b=2)也得以是table;

访问如时获得响应
rewrite2 uri : /lua_rewrite_2, a :

访问如时获得响应
rewrite2 uri : /lua_rewrite_4, a : 1

(3.1)、example.conf配置文件

location /lua_rewrite_3 {  
    default_type "text/html";  
    rewrite_by_lua_file /usr/example/lua/test_rewrite_3.lua;  
    echo "rewrite3 uri : $uri";  
} 

3.2、test_rewrite_3.lua

if ngx.req.get_uri_args()["jump"] == "1" then  
   ngx.req.set_uri("/lua_rewrite_4", true);  
   ngx.log(ngx.ERR, "=========")  
   ngx.req.set_uri_args({a = 1, b = 2});  
end 

ngx.req.set_uri(uri, true):

能够内部重写uri,即会发起新的相配location须要,等价于 rewrite ^
/lua_rewrite_4 last;
此地看error log是看不到大家记录的log。

于是恳请如会到新的location中拿走响应,此处未有/lua_rewrite_4,所以相配到/lua恳求,获得近似如下的响应

global variable : 2 ,
shared memory : 1
hello world

rewrite ^ /lua_rewrite_3; 等价于
ngx.req.set_uri(“/lua_rewrite_3”, false);

rewrite ^ /lua_rewrite_3break; 等价于
ngx.req.set_uri(“/lua_rewrite_3”, false);
加if/else判断/break/return

rewrite ^ /lua_rewrite_4 last; 等价于
ngx.req.set_uri(“/lua_rewrite_4”, true);

注意,在使用rewrite_by_lua时,开启rewrite_log
on;后也看不到相应的rewrite log。

lua_pcall

执行 Lua 函数。
首先个参数是此函数的参数个数,第二个是重回值个数,第八个是错误处理函数在栈中的索引。

5丶access_by_lua

用以访谈调控,举例我们只同意内网ip访谈,能够动用如下方式

allow     127.0.0.1;  
allow     10.0.0.0/8;  
allow     192.168.0.0/16;  
allow     172.16.0.0/12;  
deny      all;  

(1.1)、example.conf配置文件

location /lua_access {  
    default_type "text/html";  
    access_by_lua_file /usr/example/lua/test_access.lua;  
    echo "access";  
}  

(1.2)、test_access.lua

if ngx.req.get_uri_args()["token"] ~= "123" then  
   return ngx.exit(403)  
end  

即假设访谈如将获得403
Forbidden的响应。那样大家能够依照如cookie/客户token来调节是还是不是有访谈权限。

Enjoy coding

算是要从头调用了,想想还也会有一些小感动吧~

为了便利表明,大家先定义三个本子文件叫
test.lua,然后将其放在assets目录下,因为那下边包车型大巴文本不会被编写翻译。
能够运用上面的函数来读取 assets 中文件的源委:

public static String readAssetsTxt( Context context, String fileName ){
    try {
        InputStream is  = context.getAssets().open( fileName );
        int     size    = is.available();
        /* Read the entire asset into a local byte buffer. */
        byte[] buffer = new byte[size];
        is.read( buffer );
        is.close();
        /* Convert the buffer into a string. */
        String text = new String( buffer, "utf-8" );
        /* Finally stick the string into the text view. */
        return(text);
    } catch ( IOException e ) {
        e.printStackTrace();
    }
    return("err");
}
LSCValue *value = [self.context evalScriptFromString:@"return backgroundColor"];
if (value.valueType == LSCValueTypeNumber)
{
        NSInteger color = [value toInteger];
        self.view.backgroundColor = [UIColor colorWithRed:(color >> 16 & 0xff) / 255.0
                                                    green:(color >> 8 & 0xff)  / 255.0
                                                     blue:(color & 0xff) / 255.0
                                                    alpha:1.0];
}

5丶content_by_lua

此命令在此之前早已用过了,此处就不上课了。

除此以外在采取PCRE实行正则相称时须求注意正则的写法,具体法则请参谋中的SpecialPCRE Sequences部分。还大概有任何的注意事项也请阅读官方文书档案。

创建 Lua 栈

前面说了,依赖贰个虚构的栈来达成数据交流。那么首先大家本来要开创那个栈。

LuaState lua = LuaStateFactory.newLuaState(); //创建栈
lua.openLibs(); //加载标准库

lua.close(); //养成良好习惯,在执行完毕后销毁Lua栈。

然后编写翻译运转应用,则能够见见视图背景观产生了牡蛎白,如下图所示:

执行 Lua 脚本

咱俩得以选取LdoString()来试行一段轻巧的台本。

String l = "local a = 1";
lua.LdoString(l);

如此就进行了叁个相当粗略的剧本,他声称了三个全局变量l,值为1.

理所必然,也足以采取LdoFile()来加载脚本文件,不过那须要你先把脚本复制到 SD内部存款和储蓄器卡才行。因为在 APK 中是绝非“路线”可言的。

运营效果图

读取 Lua 变量与 table

首页要表明的是,独有全局变量(非 local)才得以读取。
test.lua:

a = 111;
t = {
    ["name"] = "Chenhe",
    [2] = 2222,
}

android:

lua.getGlobal("a"); //获取变量a并将值压入栈
Log.i("a", lua.toInteger(-1) + ""); //以int类型取出栈顶的值(也就是a)

lua.getGlobal("t"); //获取变量t并压入栈顶,此时table位于栈顶。
lua.getField(-1, "name"); //取出栈顶的table的name元素,压入栈顶。
Log.i("t.name", lua.toString(-1)); //以string类型取出栈顶的值(也就是t.name)

Log.i("dump",lua.dumpStack()); //输出当前栈

运作后方可知到log:

I/a: 111
I/t.name: Chenhe

I/dump: 1: number = 111.0
        2: table
        3: string = 'Chenhe'

大家曾经打响读取了 Lua 中的变量。

那样,一个简练的lua交互例子就做到了。假若您需求动态修改配置文件,能够通过和谐的数据器下发Lua配置文件到App,然后再读取新的配置文件之中的值就能够完毕动态更新了(要是是全方位App的作风配置处理进程也基本一样\_)。

执行 Lua 函数

调用 Lua 函数的貌似流程为:

  1. 获取函数并入栈。
  2. 压入种种参数(假若有)
  3. 调用函数,指明参数个数、重返值个数、错误管理函数。
  4. 收获重返值(假使有)

test.lua:

function test(a, b) 
    return a + b, a - b;
end

android:

lua.getGlobal( "test" ); //获取函数并入栈
lua.pushInteger( 5 ); //压入第一个参数a
lua.pushInteger( 3 ); //压入第二个参数b
lua.pcall( 2, 2, 0 ); //执行函数,有2个参数,2个返回值,不执行错误处理。
Log.i( "r1", lua.toInteger( -2 ) + "" ); //输出第一个返回值
Log.i( "r2", lua.toInteger( -1 ) + "" ); //输出第二个返回值
Log.i( "dump", lua.dumpStack() );

运维后得以见见log:

I/r1: 8
I/r2: 2
I/dump: 1: number = 8.0
        2: number = 2.0

这就顺理成章地实践了 Lua
函数,并赢得2个再次回到值。而在此以前入栈的函数以及参数,在实行的时候 Lua
已经弹出了,所以最后栈里只剩余2个重临值。

接下去大家来看一下LuaScriptCore的三个比较强硬的用法,那就是一贯将OC中定义的类映射到Lua中张开应用。依然拿地点的事例来进展退换,我们新建四个叫Config的连串,该项目承继LSCObjectClass类(注:必得承继该品种)。代码如下:

传入 Java 对象

得益于 Luajava 以及 Androlua
的包裹,我们得以向来将目的作为参数字传送入,并在 Lua
中央直属机关接推行对象的成员函数。

test.lua:

function setText(tv,s)
    tv:setText("set by Lua."..s);
    tv:setTextSize(50);
end

android:

lua.getGlobal("setText"); //获取函数
lua.pushJavaObject(textView); //把TextView传入
lua.pushString("Demo"); //传入一个字符串
lua.pcall(2,0,0); //执行函数,有2个参数。

home88一必发 5

实施结果

//----------------- Config.h ----------------------
#import "LSCObjectClass.h"
#import <UIKit/UIKit.h>

/**
 配置类
 */
@interface Config : LSCObjectClass

/**
 背景颜色
 */
@property (nonatomic) NSInteger backgroundColor;

/**
 初始化

 @param view 视图对象
 @return 配置对象
 */
- (instancetype)initWithView:(UIView *)view;

@end

//----------------- Config.m ----------------------

@interface Config ()

/**
 视图对象,不导出到lua的属性要加下划线
 */
@property (nonatomic, strong) UIView *_view;

@end

@implementation Config

- (instancetype)initWithView:(UIView *)view
{
    if (self = [super init])
    {
        self._view = view;
    }
    return self;
}

- (void)setBackgroundColor:(NSInteger)backgroundColor
{
    _backgroundColor = backgroundColor;
    self._view.backgroundColor = [UIColor colorWithRed:(_backgroundColor >> 16 & 0xff) / 255.0
                                                 green:(_backgroundColor >> 8 & 0xff)  / 255.0
                                                  blue:(_backgroundColor & 0xff) / 255.0
                                                 alpha:1.0];
}

@end

注入 Lua 变量

一时我们要求在 android 中开创 Lua 变量,那样就足以在 Lua
中平昔运用了。注意,这里开创的变量都以全局的(非 local)。

test.lua:

function setText(tv)
    tv:setText("set by Lua."..s); --这里的s变量由java注入
    tv:setTextSize(50);
end

android:

lua.pushString( "from java" ); //压入欲注入变量的值
lua.setGlobal( "s" ); //压入变量名
lua.getGlobal( "setText" ); //获取Lua函数
lua.pushJavaObject( textView ); //压入参数
lua.pcall( 1, 0, 0 ); //执行函数

home88一必发 6

举行理并了结果

能够看出 Lua 成功调用了 Java 注入的变量s.

接下来修改config.lua文件,增添二个开始化配置的点子,如所示:

连带链接

  • Windows 下编译 LuaJIT
  • Android 嵌入 LuaJIT
    的曲折道路
function initWithConfig( config )

    config:setBackgroundColor(0xffff00);

end

地方的Lua代码中的initWithConfig带有三个config参数,该参数正是OC中定义的Config类型,在艺术中会对config的背景颜色举办更改。

那么,viewDidLoad中平等要拓展对应的代码修改,如下所示:

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.context = [[LSCContext alloc] init];
    [self.context registerModuleWithClass:[Config class]];

    self.config = [[Config alloc] initWithView:self.view];
    [self.context evalScriptFromFile:@"config.lua"];

    [self.context callMethodWithName:@"initWithConfig" arguments:@[self.config]];
}

能够看到,LSCContext初叶化后,又调用了registerModuleWithClass方法,该措施是告诉Lua要登记一个Config的类型,那样技能够让Lua识别OC中定义的类(关于越来越多关于类型定义的从头到尾的经过能够参谋LuaScriptCore的文档)。

然后要先调用evalScriptFormFile来实践config.lua脚本(那步非常重大,必供给先执行lua文件,不然定义的不二等秘书籍是不见效的),再经过callMethodWithName方法来调用其initWithConfig的办法,并将config对象传给Lua举行操作。

接下来编写翻译运维就足以观察视图形成宝石红了,如图所示:

运行效果图

能够见到LuaScriptCore能够很方便地将Lua与原生代码结合起来使用,节省了学习Lua的C
Api所急需的光阴,让App能够做得特别动态化(Lua脚本的立异能够使利用动态地立异)。上面的七个例证只是引玉之砖,相信聪明你们利用LuaScriptCore创制到更加的多有趣有趣的东西。

终极,我想说的是LuaScriptCore是自家写的\_,该项目完全开源,有意思味也许反常的同窗可以给小编发邮件,多谢帮助~~

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图