首页 > 其他 > 详细

Lua总结二

时间:2015-02-28 23:03:57      阅读:544      评论:0      收藏:0      [点我收藏+]

Lua实践准备

刚开始练习Lua需要一个Lua解释器来执行Lua代码,我是在Windows上学习Lua的,需要自己生成最新版本的Lua解释器。
方法见于:
http://www.lua.org/manual/5.3/readme.html Building Lua on other systems
建立一个visual studio Win32 Console Application项目,把c文件和h文件分别放在Source Files和Header Files目录中,删掉luac.c文件。启动项目时会报错,按照提示增加symbol _CRT_SECURE_NO_WARNINGS,再次启动,就可以成功生成Lua解释器。

C API概述

Lua是一种嵌入式语言。即它不是一个单独运行的程序,而是一个可以链接到其他程序的库。Lua的运行从主程序开始,主程序通过C API和Lua交互,C API是一组能使C代码和Lua交互的C函数。主程序可以在Lua中注册C语言(或者其他语言)编写的新函数,Lua可以将这些新函数作为库来调用。

C和Lua有两个显著的区别:
1. C需要显式释放内存,Lua采用垃圾回收机制。
2. C使用静态类型,Lua使用动态类型。

C API的设计解决了这两个问题。C和Lua通过栈来交互。
C和Lua交互过程中需要的数据和产生的数据都在栈中,可以防止数据在使用的过程中被Lua回收掉。使用栈中的数据需要注意先使用后移除,如果弹出后再使用,则可能在使用过程中被回收。
C通过lua_pushstring/lua_pushnumber/…等方法向栈中push指定类型的值,通过lua_tostring/lua_tonumber/…等方法得到栈中指定类型的值。这样就解决了C的静态类型问题。

一个简单的Lua解释器

在这个解释器中,我们把Lua作为库来使用,首先为Lua生成一个DLL文件。
visual studio上生成和使用DLL的方法见于:
https://msdn.microsoft.com/en-us/library/vstudio/ms235636(v=vs.110).aspx
在Lua项目中搜索__declspec(dllexport),你会发现生成Lua的DLL需要添加一个symbol LUA_BUILD_AS_DLL。

有了Lua库,我们就可以编写解释器了。解释器的功能是循环读取用户输入的Lua代码并执行。

#include <stdio.h>
#include <string.h>

#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"

int main(void)
{
    char buf[256];
    lua_State *L = luaL_newstate();
    luaL_openlibs(L);

    int error = 0;
    while (fgets(buf, sizeof(buf), stdin) != NULL)
    {
        error = luaL_loadbuffer(L, buf, strlen(buf), "input") || lua_pcall(L, 0, 0, 0);
        if (error) //错误处理,打印错误消息
        {
            printf("%s\n", lua_tostring(L, -1));
            lua_pop(L, 1);
        }
    }

    lua_close(L);
    return 0;
}

C 调用Lua方法

C调用Lua方法,需要把Lua方法,参数放入栈中,然后调用lua_pcall/ lua_call…等方法。
我们准备一个Lua文件,里面定义了一个方法printName,通过C程序载入Lua文件,并调用这个printName方法。

Lua文件如下:

function printName(name)
    print("hello, my name is " .. name)
end

c代码如下:

#include <stdio.h>

#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"

int main(void)
{
    lua_State *L = luaL_newstate();
    luaL_openlibs(L);
    int error = luaL_loadfile(L, "test.lua") || lua_pcall(L, 0, 0, 0);
    if (error) //错误处理,打印错误消息,退出
    {
        printf("%s\n", lua_tostring(L, -1));
        lua_pop(L, 1);
        return 1;
    }

    lua_getglobal(L, "printName"); //获取要调用的Lua方法
    lua_pushstring(L, "xiaoming"); //Lua方法需要的参数 
    lua_pcall(L, 1, 0, 0);
return 0;
}

Lua调用C方法

Lua调用C方法,需要在Lua的Register中注册C方法:

void lua_register (lua_State *L, const char *name, lua_CFunction f);

C方法的格式为:

typedef int (*lua_CFunction) (lua_State *L);

示例:修改Lua文件,调用C方法。

function printName(name)
    if checkName(name) then  --checkName为C方法
        print("hello, my name is " .. name)
    end
end

在C中定义checkName方法

static int checkName(lua_State *L)
{
    char *name = lua_tostring(L, -1); //获取参数name
    int res = strcmp(name, "GM");
    lua_pop(L, 1); //弹出参数name
    lua_pushboolean(L, res); //返回结果
    return 1; //结果个数
}

C的主程序,在Lua中注册checkName方法,调用Lua的printName方法。

int main(void)
{
    lua_State *L = luaL_newstate();
    luaL_openlibs(L);
    luaL_loadfile(L, "test.lua");  //不考虑出错情况
    lua_pcall(L, 0, 0, 0);

    lua_register(L, "checkName", checkName); //注册C函数

    lua_getglobal(L, "printName");
    lua_pushstring(L, "xiaoming"); //lua_pushstring(L, "GM"); 不会输出任何内容
    int error = lua_pcall(L, 1, 0, 0);
    if (error)
    {
        printf("%s\n", lua_tostring(L, -1));
        lua_pop(L, 1);
        return 1;
    }

    return 0;
}

C是面向过程的语言,C方法和Lua方法是一致的,很容易注册到Lua当中。像C++/Java/C#…面向对象的语言,很多方法存在于对象上,这些方法要如何注册呢?

《Lua游戏开发实践指南》第11章 Lua驱动的GUI介绍了一种方法,为各种对象创建一个管理器,通过type和id可以查找到任意对象。比如对象上有方法draw(…),在管理器中定义方法draw(type, id, …),该方法内部获得对象,调用对象上的draw(…)方法。最后注册到Lua中的方法是管理器的中draw方法。

KopiLuaInterface采用了另外一种做法,把一个C#对象放入Lua中,可以像在C#里一样使用这个对象。
把C#对象放入Lua容器中:
Lua lua = new Lua();
lua[“dt”] = DateTime.Now;
在Lua中使用C#对象
print(dt.GetType, type(dt))
这个C#对象以userdata的方式放入Lua容器,之所以可以在userdata上调用GetType之类的方法,是因为这个userdata定义了元方法__index。

参考资料
《Lua程序设计》第二版
《Lua游戏开发实践指南》
Lua 5.3参考手册:http://www.lua.org/manual/5.3/
KopiLuaInterface:https://github.com/gfoot/kopiluainterface

Lua总结二

原文:http://blog.csdn.net/darwinchina/article/details/43991527

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!