Lua学习笔记

Lua学习笔记
 

目录
Lua学习笔记    1
需求    2
选型    2
Python    2
Lua    3
分析    4
环境    4
下载所需依赖    4
环境配置    4
代码    5
代码结构如下    5
Monster.java    5
LuaDemo.java    7
MyMonsterThread.java    8
LuaTest.java    9
demo.lua    13
问题    18
总结    19

需求
在游戏开发过程中,由于需要支持不同的手机平台,如winPhone、android、iphone等,这样,一套游戏逻辑就需要重新开发多次,而这部分游戏逻辑是与平台无关的,可以单独实现,如果这部分逻辑提炼出来,嵌入到不同的语言中,将会使得维护起来更加方便;
另外,服务器后台在处理游戏逻辑的时候,同样会出现游戏逻辑经常出现变化的情况,比如任务系统的更新等,这样,如果游戏逻辑直接写到code中,会造成每次更新都需要重启服务的情况,我们希望实现热更新,尤其是业务逻辑模块方面的变化,当出现多服的情况下,这部分的更新会更麻烦;
还有就是游戏设计师与程序员沟通的问题,当设计师设计出一套场景后,需要程序员去实现才能看到具体的结果,沟通费时费力还不一定达到预期的效果,如果出现一种脚本语言使得设计师不需要依赖程序员即可独立设计并表现出游戏场景,同时设计师与程序员都熟悉这种脚本语言,则对双方都受益。

选型
市面上出现的适合于游戏开发的脚本语言主要有Python与Lua,因为这两种脚本语言都可以直接调用C++功能(虽然我是一个java程序员,但不得不承认,绝大部分的好玩的大型游戏都是基于C++实现的),事实上,这两种脚本语言的兼容性与扩展性都非常好(都可以集成到Java中)

关于Python与Lua的对比(http://lua-users.org/wiki/LuaVersusPython)
Python
扩展模块更加完善。含有大量的有用的函数库,非常利于线下工作,如作为工具脚本。另外还有大量的教程。
通过附加模块可实现极为出色的多维数组数值计算能力(个人认为在做机器学习算法等数学模型应用中可能会更合适),严格的说,Lua并没有数组的概念,所有的数据结构都是以table形式存储的。
自带ctypes数据类型。可以访问动态链接库(.so文件或.dll文件),无需对C进行扩展。、
支持远程调试。
Lua有一个简约的不能再简单的语法,这点上与Python没有较大差别。
Python对string与list做了较大层度的扩展,我建议如果想要在Lua中更有成效,就去使用扩展库

Python对Unicode编码的支持更好些
Python对空白字符敏感
Python内置了按位操作,Lua可通过扩展库实现
Python具有错误检测能力,而在这方面,Lua更易出错
Python有更为详细的初学者文档,目前尚缺乏对Lua介绍的入门教程
 
Lua
Lua比Python小巧的多,python22.dll 824KB,而一个基本的lua引擎仅在100KB以下
占用内存更少
看起来没有任何的指针使用
编译器与解释器执行起来更快
在脚本与C语言中,仅用少量的"胶水代码"即可实现较为优雅且简单的API交互
不适用可以得到复杂而易出错对象的引用计数
Lua以作为一门配置语言开始,在需要创建与配置文件的时候(尤其是在游戏中),他是非常了不起的
Lua有一个非常漂亮且简单强大的语法,与Python相比,可以用更少的代码
Lua有一个小巧简单稳定的代码库,如果需要,查看与修改很容易,但可能文档不如Python完善

Lua很少有扩展组件使之更易为一个专门的需要做绑定,Python则需要众多的模块
Lua支持多线程操作,多个解释器可以同存于一个进程中,每一个解释器都可以在自己的线程中独立运行,因此,Lua更适合在多线程程序中嵌入
Lua对空白字符不敏感
Lua支持多线程开箱即用,可在一个单独的线程或进程中有多个解释器,而Python不支持多线程,多线程可以访问解释器,但需要每个线程都必须持有全局锁

分析
通过以上分析,在做独立的运行程序或脚本时候,采用Python是一个不错的选择(如线下分析等任务),而作为脚本嵌入到另外一种语言中,更推荐使用Lua
环境
下载所需依赖
Win32:
Win64 :
其他环境:下载地址:http://www.keplerproject.org/luajava/index.html#download

源码以及文档:
教程:
环境配置
将luajava-1.1.dll加入到jre的bin目录下
将luajava-1.1.jar引入到工程的环境变量中
下载lua的eclipse插件Lua Development Tools
如需单独调试Lua,则需要单独安装LuaForWindows 编译器
代码
代码结构如下
Monster.java
package com.chilijoy.bean;
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
/*******************************************************************************
*
* Monster.java Created on 2014年7月28日
*
* Author: linfenliang
*
* Description:
*
* Version: 1.0
******************************************************************************/
public class Monster {
    private String race;//种族
    private int defense;//防御值
    private int attack;//攻击值
    private int life;//生命值
    public String getRace() {
        return race;
    }
    public void setRace(String race) {
        this.race = race;
    }
    public int getDefense() {
        return defense;
    }
    public void setDefense(int defense) {
        this.defense = defense;
    }
    public int getAttack() {
        return attack;
    }
    public void setAttack(int attack) {
        this.attack = attack;
    }
    public int getLife() {
        return life;
    }
    public void setLife(int life) {
        this.life = life;
    }
    @Override
    public String toString() {
        return ReflectionToStringBuilder.toString(this);
    }
}

LuaDemo.java
package com.chilijoy.lua;
import java.io.File;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/*******************************************************************************
*
* LuaDemo.java Created on 2014年7月28日
*
* Author: linfenliang
*
* Description:
*
* Version: 1.0
******************************************************************************/
public class LuaDemo {
    public static final String luaPath = "." + File.separator + "conf" + File.separator ;
    public static void main(String[] args) {

        ExecutorService service = Executors.newSingleThreadExecutor();

        for(int i=0;i<500000;i++){
            service.execute(new MyMonsterThread());
        }
        service.shutdown();
    }
}

MyMonsterThread.java
package com.chilijoy.lua;
import java.io.File;
import org.keplerproject.luajava.LuaState;
import org.keplerproject.luajava.LuaStateFactory;
import com.chilijoy.bean.Monster;
/*******************************************************************************
*
* MyMonster.java Created on 2014年7月28日
*
* Author: linfenliang
*
* Description:设计存在多次打开关闭问题,弃用
*
* Version: 1.0
******************************************************************************/
 
public class MyMonsterThread extends Thread {
    static final String luaPath = "." + File.separator + "conf" + File.separator + demo.lua";
 
    @Override
    public void run() {
        LuaState lua = null;
        try {
            Monster m = new Monster();
            // System.out.println("monster_before:" + m);
            lua = LuaStateFactory.newLuaState();
            lua.openLibs();
            lua.LdoFile(luaPath);
            lua.getField(LuaState.LUA_GLOBALSINDEX, "create");
            // lua.pushObjectValue(monster);
            lua.pushJavaObject(m);
            lua.call(1, 0);
            // System.out.println("monster_after:" + m);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (lua != null) {
                lua.close();
            }
            System.out.println(this.getName());
        }
    }
}
 
 
LuaTest.java
 
 
package com.chilejoy.lua;
 
 
import java.util.ArrayList;
import java.util.Iterator;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
 
import org.junit.Assert;
import org.junit.Test;
import org.keplerproject.luajava.LuaException;
import org.keplerproject.luajava.LuaObject;
import org.keplerproject.luajava.LuaState;
import org.keplerproject.luajava.LuaStateFactory;
 
import com.chilijoy.bean.Monster;
import com.chilijoy.lua.LuaDemo;
import com.chilijoy.lua.MyMonsterThread;
 
/*******************************************************************************
 
* LuaTest.java Created on 2014年7月28日
 
* Author: linfenliang
 
* Description:
 
* Version: 1.0
 
******************************************************************************/
 
public class LuaTest {
    static final int cycleTimes = 1000;
    @Test
    public void test() throws LuaException {
        System.out.println("-------input object test-------");
        LuaState lua = null;
        Monster m = new Monster();
        System.out.println("monster_before:" + m);
        lua = LuaStateFactory.newLuaState();
        lua.openLibs();
        lua.LdoFile(LuaDemo.luaPath + "demo.lua");
        lua.getField(LuaState.LUA_GLOBALSINDEX, "create");
        // lua.pushObjectValue(monster);
        lua.pushJavaObject(m);
        lua.call(1, 1);//传入一个参数,传出1个参数
        lua.setField(LuaState.LUA_GLOBALSINDEX, "monster");
        LuaObject obj = lua.getLuaObject("monster");
        System.out.println("monster_lua:"+obj.getObject());
        System.out.println("monster_after:" + m);
        Assert.assertEquals(obj.getObject(), m);
        lua.close();
    }
    @Test
    public void testHelloWorld(){
        System.out.println("-------hello ,world test-------");
        LuaState lua = LuaStateFactory.newLuaState();
        lua.openLibs();
        lua.LdoFile(LuaDemo.luaPath + "demo.lua");
        lua.getField(LuaState.LUA_GLOBALSINDEX, "hello");
        lua.call(0, 0);
        lua.close();
    }
    @Test
    public void calculateTest(){
        
        System.out.println("--------calculate---------");
        LuaState lua = null;
        lua = LuaStateFactory.newLuaState();
        lua.openLibs();
        lua.LdoFile(LuaDemo.luaPath + "demo.lua");
        lua.getField(LuaState.LUA_GLOBALSINDEX, "calculate");
        lua.pushNumber(3);
        lua.pushNumber(5);
        lua.pushNumber(8);
        lua.call(3, 1);
//        lua.setField(LuaState.LUA_GLOBALSINDEX, "result");
//        LuaObject obj = lua.getLuaObject("result");
        LuaObject obj = lua.getLuaObject(1);
        System.out.println("calculate result:"+obj.getNumber());
        lua.close();
    }
    @Test
    public void multipleReturnValueTest(){
        System.out.println("--------multipleReturnValue---------");
        LuaState lua = null;
        lua = LuaStateFactory.newLuaState();
        lua.openLibs();
        lua.LdoFile(LuaDemo.luaPath + "demo.lua");
        
        lua.getField(LuaState.LUA_GLOBALSINDEX, "getValues");
        lua.pushNumber(3);
        lua.pushNumber(5);
        lua.pushNumber(8);
        lua.call(3, 3);
        for(int i=1;i<=3;i++){
            LuaObject o1 = lua.getLuaObject(i);
            System.out.println("获取第"+i+"个返回值:"+o1.getNumber());
        }
        
        lua.close();
    }
    @Test
    public void nestedFuncTest(){
        System.out.println("------------nestedFunc-----------");
        LuaState state = LuaStateFactory.newLuaState();
        state.openLibs();
        state.LdoFile(LuaDemo.luaPath+"demo.lua");
        
        state.getField(LuaState.LUA_GLOBALSINDEX, "nestedFunc");
        state.pushNumber(3);
        state.pushNumber(5);
        state.pushNumber(8);
        state.call(3, 1);
        LuaObject obj = state.getLuaObject(1);
        System.out.println("nestedFunc 返回值:"+obj.getNumber());
        state.close();
    }
    
    @Test
    public void cycleTest(){
        System.out.println("--------cycle(for(){}) ---------");
        LuaState state = LuaStateFactory.newLuaState();
        state.openLibs();
        state.LdoFile(LuaDemo.luaPath + "demo.lua");
        double a,b,c;
        for(int i=0;i<cycleTimes;i++){
            a= Math.random();
            b = Math.random();
            c = Math.random();
            state.getField(LuaState.LUA_GLOBALSINDEX, "calculate");
            state.pushNumber(a);
            state.pushNumber(b);
            state.pushNumber(c);
            state.call(3, 1);
//            state.setField(LuaState.LUA_GLOBALSINDEX, "result");
//            LuaObject obj = state.getLuaObject("result");
            LuaObject obj = state.getLuaObject(1);
            state.pop(1);
            System.out.println(String.format(" a=%6f,b=%6f,c=%6f sum=>%6f", a,b,c,obj.getNumber()));
        }
        state.close();
    }
//    @Test
    public void concurrentTest() throws InterruptedException {
        System.out.println("--------concurrent ---------");
        ExecutorService service = Executors.newFixedThreadPool(5);
        for(int i=0;i<cycleTimes;i++){
            service.execute(new MyMonsterThread());
        }
        Thread.sleep(5000);
        service.shutdown();
    }
//    @Test
    public void concurrentSingleThreadTest() throws InterruptedException {
        System.out.println("--------concurrentSingleThread ---------");
        ExecutorService service = Executors.newSingleThreadExecutor();
        for(int i=0;i<cycleTimes;i++){
            service.execute(new MyMonsterThread());
        }
        service.shutdown();
    }
    @Test
    public void testFunc() throws InterruptedException{
        System.out.println("-----------testFunc-----------");
        LuaState state = LuaStateFactory.newLuaState();
        state.openLibs();
        state.LdoFile(LuaDemo.luaPath+"demo.lua");

        

        state.getField(LuaState.LUA_GLOBALSINDEX, "testFunc");

        state.call(0, 0);

        state.close();

//        System.out.println(Math.toRadians(30));

//        System.out.println(Math.sin(Math.toRadians(30)));

    }

}

 

 

demo.lua

 

--对monster赋值(传入对象,返回对象)

function create(monster)

monster:setRace("the first demo")

monster:setDefense(10)

att = monster:getAttack()

print("monster.attack=>"..att)

monster:setAttack(10-att)

monster:setLife(100)

print("create monster !");

return monster

end

 

--打印输出测试

function hello()

    print("Hello World from Lua !");

end

--数值计算结果输出

function calculate(a,b,c)

    return a+b+c

end

--多返回值测试

function getValues(a,b,c)

return a,b,c

end

--函数嵌套调用

function nestedFunc(a,b,c)

printFunc()

    return calculate(a,b,c)

end

function printFunc()

print("提供给nestedFunc 函数调用的打印函数 !");

end

function testFunc()

print("------LUA-----testFunc--------START-----")

a=1

b="123"

c={4,5,6}

d=hello

print(type(a))--打印数据类型

print(type(b))

print(type(c))

print(type(d))

print(_VERSION)--_VERSION 打印LUA版本

print( a, b,c, d)--多个返回值输出

--多行数据

reservedWords =[[Lua reserved words are:

and, break, do, else, elseif,end, false,

for, function, if, in, local, nil, not,

or,repeat, return, then, true, until, while]]

print(reservedWords)

 

--多个变量赋值

a1,a2,a3=1,"2_",3

print(a1,a2,a3)

--数据互换

b1,b2=3,5

print(b1,b2)

b1,b2=b2,b1

print(b1,b2)

 

a,b,c,d,e = 1, 1.123, 1E9, -123, .0008

print("a="..a, "b="..b, "c="..c, "d="..d, "e="..e) --字符串连接用 .. 取代"+"

 

 

io.write("io.write writes to stdout but without new line.")

io.write(" Use an empty print to write a single new line.")

print()

 

a={} -- {} empty table

b={1,2,3}

c={"a","b","c"}

print(a,b,c) -- tables 不能被直接打印

 

---------测试object格式数据----------------

user={}

user.username="linfenliang"

user.password="123456"

user.age=26

user.isMan=true

 

if(user.age>20) then

print(user.username ,"is more than 20 years old!")

elseif(user.age>10) then

print(user.username, "maybe a student")

else

print(user.username, "is just a little boy ")

end

 

if(user.username=="linfenliang") then

print("yes,I am linfenliang !")

else

print("sorry,you got the wrong guy!")

end

 

print(user.username,user.password,user.age,user.isMan)

 

judge(user)

 

 

 

print "------LUA-----testFunc --------END -----" --也可不添加括号

end

--如果 age==26,则address为 shanghai,否则为 not in shanghai

function judge(user)

user.address = (user.age==26) and "I am in Shanghai" or "I am not in Shanghai"

print(user.address)

 

while(user.age~=30) do

user.age=user.age+1

io.write(" My age is growing ..."..user.age)

end

 

print()

 

repeat

user.age=user.age-1

print(" I am beginning young "..user.age)

until user.age==26

 

-- 从1到4依次打印

for a=1,4

do print(a)

end

 

print()

-- 从1到6,每次增长3

for a=1,6,3

do print(a)

end

print()

--pairs 迭代table元素

for key,value in pairs({12,8,9,7})

do print(key,value)

end

 

arr = {1,2,3,"four","five",6}

for k,v in pairs(arr)

do print(k,v)

end

 

a=0

while true do

a=a+1

if a==10 then

break

end

end

print("循环累加:"..a)

--全局变量与局部变量测试

sayHello()

print(word_a,word_b)

--字符串格式化测试

io.write(string.format("hello,now is %s, I am %s, I am %s",os.date(),"linfenliang","a good man!
"))

--数学公式测试

print(math.sqrt(81),math.pi,math.sin(0.5235987755982988))

--字符串操作

--string.byte, string.char, string.dump, string.find, string.format,

--string.gfind, string.gsub, string.len, string.lower, string.match,

--string.rep, string.reverse, string.sub, string.upper

print(string.reverse("abcdefg"),string.rep("abcd",5),string.find("abcdeadvdsrerdv","dv"))

--table测试

t = {1}

table.insert(t,2)

table.insert(t,3)

table.sort(t,function(v1,v2) return v1>v2 end)

print("table t==>"..table.concat(t,":"))

table.insert(t,"iii")

--输出

for k,v in ipairs(t)

do print(k,v)

end

--Lua IO 操作

-- IO 函数:

-- io.close , io.flush, io.input, io.lines, io.open, io.output, io.popen,

-- io.read, io.stderr, io.stdin, io.stdout, io.tmpfile, io.type, io.write,

-- file:close, file:flush, file:lines ,file:read,

-- file:seek, file:setvbuf, file:write

 

print(io.open("E://demo.lua","r"))

 

--os.clock, os.date, os.difftime, os.execute, os.exit, os.getenv,

--os.remove, os.rename, os.setlocale, os.time, os.tmpname

print(os.date())

 

dofile("E://demo.lua")

 

str_01 = "print("Hello,this function is load from String!")"

loadstring(str_01)()

math.randomseed(os.time())

a = math.random(10,20)

b = math.random(10,20)

c = math.random(10,20)

d = math.random(10,20)

e = math.random(10,20)

f = math.random(10,20)

print(a,b,c,d,e,f)

 

end

word_a = "hello"

--测试本地变量与全局变量

function sayHello()

local word_a = "nihao"

word_b = "I am good"

print(word_a,word_b)

end

问题

1、在做并发测试时,发现如果多次创建关闭 LuaState,会出现异常,甚至会导致JVM崩溃,分析原因可能为加载编译器与执行器占用内存过大导致,但是我将JVM内存参数改为512MB还是会出现这个问题,还是有疑问。

总结

一直没有找到一个比较典型的使用案例,《Lua游戏开发实践指南》有些例子,还在研究。
Lua 调用自定义C模块
这是《Lua程序设计》中提到的,但是想成功执行,对于初学Lua的确没那么简单。这里涉及如何如何生成一个动态链接库so文件;Lua5.2中导出函数从LuaL_register变成了LuaL_newlib。对于具体的细节有待深入。这里的模块名是hello_lib, Lua解释器会根据名字找到对应的模块,而后执行其中的 luaopen_XXX方法。
Lua程序设计(第2版)中文 PDF http://www.linuxidc.com/Linux/2013-03/81833.htm
代码:
#include <math.h>
#include <lua5.2/lua.h>
#include <lua5.2/lauxlib.h>
#include <lua5.2/lualib.h>
static int hello_sin(lua_State *L){
    double d = luaL_checknumber(L, 1);
    lua_pushnumber(L, sin(d));
    return 1;
}
static const struct luaL_Reg hello_lib[] = {
    {"hello_sin" , hello_sin},
    {NULL, NULL}
};
int luaopen_hello_lib(lua_State *L){
    luaL_newlib(L, hello_lib);
    //luaL_register(L, "hello_lib",hello_lib); // lua 5.1
    return 1;
}

在Lua中调用:
local hello = require "hello_lib"
print(hello.hello_sin(1))
执行过程和结果:
Lua 调用自定义C模块
Lua 语言 15 分钟快速入门 http://www.linuxidc.com/Linux/2013-06/86582.htm
Lua程序设计(第二版)阅读笔记 http://www.linuxidc.com/Linux/2013-03/81834.htm
NetBSD 将支持用 Lua 脚本开发内核组件 http://www.linuxidc.com/Linux/2013-02/79527.htm
CentOS 编译安装 Lua LuaSocket http://www.linuxidc.com/Linux/2011-08/41105.htm
lua读写redis的环境部署
我的lua环境是5.2版本,而对应的lua redis接口都是基于5.1的。所以首先先安装
1. compact5.1 这个安装没什么好说的,搜到官方网站,下载即可。然后copy对应lua文件到lua对应的安装库路径
我这里是/usr/local/lib/lua/5.2/
2.  安装luasocke, 这个接口是实现了lua基本的网络请求接口。这个安装麻烦一点,对应的参考http://blog.csdn.net/shiningstarpxx/article/details/12911569
3. 安装redis-lua-git, 把对应的src目录下的lua文件拷到对应的库路径即可。
测试下面的代码,如果成功了就说明安装成功
local redis = require 'redis'
local myclient = redis.connect('127.0.0.1', 6379)
response = myclient:ping()
print( response )
myclient:set("10000", "Hello World");
value = http://blog.csdn.net/shiningstarpxx/article/details/myclient:get("10000")
print(value)
hello world

增加nginx配置:
        location /hello {
            default_type text/html;
            content_by_lua '
                ngx.say("<p>hello, world</p>")
ngx.say(tostring(ngx.var.remote_addr),"<br/>")
ngx.say(tostring(ngx.var.arg_name),"<br/>")
            ';
        }


这样就可以使用nginx开发动态接口了。
niginx的其他参数:
非常多的扩展和使用方法
https://github.com/chaoslawful/lua-nginx-module
3,连接数据库redis

 local mysql = require "resty.mysql"
    local memcached = require "resty.memcached"
    local function query_mysql()
        local db = mysql:new()
        db:connect{
                    host = "127.0.0.1",
                    port = 3306,
                    database = "test",
                    user = "monty",
                    password = "mypass"
                  }
        local res, err, errno, sqlstate =
                db:query("select * from cats order by id asc")
        db:set_keepalive(0, 100)
        ngx.say("mysql done: ", cjson.encode(res))
    end
    local function query_memcached()
        local memc = memcached:new()
        memc:connect("127.0.0.1", 11211)
        local res, err = memc:get("some_key")
        ngx.say("memcached done: ", res)
    end

ngx.thread.spawn(query_mysql)      -- create thread 1
    ngx.thread.spawn(query_memcached)  -- create thread 2 
 几行lua代码计算http包总长度 
--帮助理解一下lua里的字符串模式和捕获的使用
--计算HTTP包总长度
local i, j = pMsg:find("

")
if(i ~= nil and pkgsize == 0) then
    --字符串模式匹配加捕获,j是HTTP头的长度
    pkgsize = j + tonumber(pMsg:match("Content%-Length: (%d+)"))
end

一起学Lua(第二篇-环境搭建)

(2011-07-28 01:17:30)
标签:

杂谈

 

一、LuaForWindows

在搭建环境之前,肯定要一个Lua的解释器之类的东西,这些东西从哪里来?

1.直接编译文件

(1)http://www.lua.org/download.html下载新版本的Lua

(2)解压进入etc/

C:Documents and SettingsAdministrator>cd /d f:lua_study/lua-5.1.4/etc 

(3)执行 luavs.bat

F:lua_studylua-5.1.4etc>luavs.bat 

(4)src目录下生成动态库等等文件,不过我在编译的时候出现了好多问题,就使用的下面的方法

2.使用LuaForWindows

Lua for Windows 为 Windows 系统下提供了 Lua 脚本语言的开发和运行环境,很多东西配套好了。

直接像python一样安装一下,安装时把SciTe编辑器也选择上,像头文件,库什么的都直接放好了。

推荐这种方法

3.SciTe编辑器

是一个体积小巧的文本编辑器,在安装LuaForWindows可以选择安装,并且把那个黑底色选择上更有感觉一点。

4.下载地址

http://code.google.com/p/luaforwindows/

或者

http://luaforge.net/frs/?group_id=377

二、Script.Net的IDE环境

蓝蚂蚁软件工作室的一个作品,用着感觉不错,用这个也是相当的方便,最主要的是它有vc番茄一样的提示

下载地址:http://www.blueantstudio.net

先下载 基础安装包,再下载安装Lua开发包

一起学Lua(第二篇-环境搭建) - 熊哥 - 熊哥

三、第一个Lua程序

print("hello lua...")

SciTe编辑器中:

一起学Lua(第二篇-环境搭建) - 熊哥 - 熊哥

四、Lua和VS2008的环境

1.加入外部的头和库

VS2008-工具-选项-VC++目录中,把LuaForWindows安装下的头文件和库文件加到目录,运行文件在安装LuaForWindows的时候加入了环境变量,可以不用加了。
一起学Lua(第二篇-环境搭建) - 熊哥 - 熊哥

2.第一个工程

新建一个vc的命令行工程,写一个Lua脚本,用C++调用。

脚本:environment_test.lua

function ShowPrint() 
    print( "this is my cpp code call..." ) 
end

C++工程:Lua_c_evn

//注释:这段代码是参考网上文章照猫画虎出来的,只是来验证环境正确。

  1: //------------------------------------------------- 
  2: //说明:Lua环境测试 
  3: //时间:2011-7-28 
  4: //环境:vs2008 
  5: //------------------------------------------------- 
  6: #include "stdafx.h" 
  7: #include <iostream> 
  8:  
  9: extern "C" {    
 10: #include <lua.h> 
 11: #include <lualib.h> 
 12: #include <lua.hpp> 
 13: } 
 14:  
 15: #pragma comment(lib,"lua5.1.lib")   
 16:  
 17: int _tmain(int argc, _TCHAR* argv[]) 
 18: { 
 19:   lua_State *L = lua_open(); // 
 20:   luaL_openlibs(L); //加载 .lib 文件  
 21:  
 22:   // 加载脚本文件,需要放在程序目录   
 23:   luaL_loadfile( L, "environment_test.lua" );   
 24:   lua_resume( L, 0 );   
 25:  
 26:   // 调用函数   
 27:   lua_getglobal( L, "ShowPrint" );   
 28:   if( lua_resume( L, 0 ) )   
 29:   { 
 30:     printf( "%s/n", lua_tostring( L, 1) );   
 31:   } 
 32:    
 33:   // 调用结束   
 34:   lua_close(L);   
 35:  
 36:   std::system("pause");   
 37:  
 38:   return 0; 
 39: } 
 40:  
 41: 

直接运行,结果

一起学Lua(第二篇-环境搭建) - 熊哥 - 熊哥

OK,环境配置看来是正确了,之后,就开始真正的Lua之旅了。

五、参考引用

所有文章您都可以任意转载,修改,演绎,但请保持完整性并留个大妈般的出处,不要误导他人

本文出处(熊哥)

http://pppboy.blog.163.com/blog/static/30203796201162811730972/

引用申明

http://blog.csdn.net/kingsollyu/article/details/6613468

http://blog.csdn.net/kun1234567/article/details/1929815

http://baike.baidu.com/view/1207529.htm

生产环境中 Ngx_lua 使用技巧和应用的范例

2013-09-10 17:25:05     发表评论

   Rewrite phase.

   Access phase.

   Content phase.

详细的步骤:

1.init_by_lua  上下文http  ngx启动时执行
2. set_by_lua  上下文 server, server if, location, location if
3.rewrite_by_lua 上下文  http, server, location, location if
4.access_by_lua 上下文 http, server, location, location if
5.content_by_lua 上下文   location, location if
6.header_filter_by_lua 上下文   http, server, location, location if
7.body_filter_by_lua 上下文 http, server, location, location if
8.log_by_lua 上下文 http, server, location, location if

咱们再过滤post、get请求或者是触发了某个access、rewrite,如果发现恶意和违规的侵入的话,可以发邮件报警,好让我们第一时间收到邮件的信息。

location = /smtp {
        default_type "text/plain";
        content_by_lua '
            local smtp = require("socket.smtp")
            local from = "<ruifengyunceshi@163.com>"
            local  rcpt = {"",}
            local   mesgt = {
            headers = {
            to = "", -- 收件人
            subject = "This is Mail Title"
            },
        body = "This is  Mail Content."
    }
     local  r, e = smtp.send{
        server="smtp.163.com",
        user="",
        password="",
        from = from,
        rcpt = rcpt,
        source = smtp.message(mesgt)
      }
    if not r then
        ngx.say(e)
    else
        ngx.say("send ok!")
    end
    ';
    }

lua这东西挺怪的,他的双引号和单引号是有很大区别的,我到现在也没搞明白,啥区别,反正用双引号就对了。。。有事error.log报错的话,改成单引号试试。。

好点的方法是  先在lua的环境中跑一边,ok后,在放到ngx_lua里面。

Lua有丰富的接口的方案,不只是给别人提供的接口,还有他自己访问别的接口所用的模块。

如果你的同事那边已经有个高性能的socket接口,那你就别麻烦他改成rest模式了。毕竟socket对socket速度很快的。

location /cosocket {
        default_type "text/plain";
        content_by_lua '
        local sock = ngx.socket.tcp()
        sock:settimeout(1000)
        local ok, err = sock:connect("127.0.0.1", 12000)
        if not ok then
            ngx.say("failed to connect: ", err)
            return
        end
        local bytes, err = sock:send("flush_all")
        ngx.say(bytes,err)
        if not bytes then
            ngx.say("failed to send query: ", err)
            return
        end
       local line, err = sock:receive()
        if not line then
            ngx.say("failed to receive a line: ", err)
            return
        end
        ngx.say("result: ", line)
        ';
      }
                                                                                                                                                                                                                                                                                                                                                                                         
    }
}

对于给别人的mysql查询,给账号密码不合适,和一个小权限的账号密码也不合适。

这种情况,我们要是求高性能的话,可以用lua配置cjson做成rest接口。

location /select2 {
content_by_lua '
local mysql = require "resty.mysql"
local db,err = mysql:new()
if not db then
ngx.say("failed to instantiate mysql: ",err)
return
end
db:set_timeout(1000)
local ok,err,errno,sqlstate = db:connect{
host = "127.0.0.1",
port = 3306,
database = "niubi",
user = "ruifengyun",
password = "",
max_package_size = 1024
}
if not ok then
ngx.say("failed to connect: ", err, ": ", errno, " ", sqlstate)
return
end
ngx.say("connected to mysql.")
res,err,errno,sqlstate = db:query("select username,password from users where id="..ngx.var.arg_id)
if not res then
ngx.say("bad result: ", err, ": ", errno, ": ", sqlstate, ".")
return
end
local cjson = require "cjson"
ngx.say("result: “,cjson.encode(res))
';
}

咱们既然知道了 lua的强大之处, 可以从lua里面搞负载均衡。

往redis里面 扔两个key   比如 web1 8.8.8.111  web2 8.8.8.222

server {
  listen 80;
  server_name _;
  server_name_in_redirect off;
  port_in_redirect off;
  root /root/html;
  location / {
    set $upstream "";
    rewrite_by_lua '
      local routes = _G.routes
      -- setup routes cache if empty
      if routes == nil then
        routes = {}
        ngx.log(ngx.ALERT, "Route cache is empty.")
      end
      -- try cached route first      local route = routes[ngx.var.http_host]
      if route == nil then
        local redis  = require "redis"
        local client = redis.connect("localhost", 6379)
        route        = client:get(ngx.var.http_host)
      end
      if route ~= nil then
        ngx.var.upstream = route
        routes[ngx.var.http_host] = route
        _G.routes = routes
      else
        ngx.exit(ngx.HTTP_NOT_FOUND)
      end
    ';
    proxy_buffering             off;
    proxy_set_header            Host $host;
    proxy_set_header            X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_redirect              off;
    proxy_connect_timeout       10;
    proxy_send_timeout          30;
    proxy_read_timeout          30;
    proxy_pass                  http://$upstream;
  }
}

用lua 对cookie的控制

header_filter_by_lua '
        t = {}
        if ngx.var.http_cookie then
            s = ngx.var.http_cookie
            for k, v in string.gmatch(s, "(%w+)=([%w%/%.=_-]+)") do
                t[k] = v
            end
        end               
        p = ngx.req.get_uri_args()                                                     
        if not t.uid and p.uid then
            expires = ngx.cookie_time(4523969511)
            ngx.header["Set-Cookie"] = {"uid=" .. p.uid .."; expires=" .. expires .. ";
        end
                                                     
';
原文地址:https://www.cnblogs.com/timssd/p/4753595.html