lua为C写插件的方法

   lua是一种可扩展的语言,因为它的解释器是C的一个应用程序。这就允许了C可以调用lua写的库,lua也可以调用C为它扩展的库;网络游戏中常用的是lua作为C的插件来使用的。本文主要是针对lua为C写插件的用法做一个小的总结。
 
 需要用到的头文件:
    lua.h: 定义了lua的基础函数,包括创建lua环境、调用lua函数,读写lua环境中全局变量,以及注册供lua调用的新函数。
    lauxlib.h:定义了辅助库(auxiliary library, auxlib)提供的函数。它的所有定义都是以luaL_开头的。
    lualib.h:定义了打开标准库的函数。
 
C月lua的数据交互主要依靠的是lua的虚拟栈。虚拟栈的存在是为了解决lua的垃圾回收机制;几乎所有的API都会用到这个虚拟栈;这个栈也严格遵守先进后出的原则。
 
查询这个栈的数据一般分为从头部查找和从尾部查找两种方式。 默认情况下top的指针是指向索引为0的位置的,所以如果要从头开始查找的话一般用负数表示栈顶的元素,如-1表示栈顶,-2表示栈顶下方的一个元素;如果要从尾部开始查找的话,一般用正数表示;因为第一个压入栈的原素索引为1,即栈底的元素索引为1,第二个压入栈的元素索引为2,以此类推。
 
在为C写插件的时候,需要做的事情有:
1. 打开lua
2. 打开lua的标准库
3. 调用lua的函数
4. 传参数
5. 获取结果(结果会自动保存在虚拟栈中),将结果从虚拟栈中弹出。
 
下面是一个用lua为C写配置文件的一个例子:
 
config.lua是协议对应的数字的表:
#!/usr/bin/lua

protocols={
        HOPOPT = 0,
        ICMP = 1,
        IGMP = 2,
        GGP = 3,
        IP = 4,
        ST = 5,
        TCP = 6,
        CBT = 7,
        EGP = 8,
        IGP = 9
}
lua_protocol.lua负责将传入进来的字符串如"protocol=tcp"解析并查表得到tcp对应的值并传回:
#!/usr/bin/lua
function lua_protocol(str)
        local index = string.find(str, "=")
        local p_t = {}
        local res;
        if index then
                local _, _, key, value = string.find(str, "(%a+)%s*=%s*(%w+)")
                p_t.key = key
                p_t.value = value
        else
                p_t.value = value
        end

        if string.find(p_t.value, "%a+") then
                local t = p_t.value
                if assert(loadfile("configs.lua")) then
                        dofile("configs.lua")
                        res = protocols[""..t..""]
                else
                        res = nil
                end

        elseif string.find(p_t.value, "%d+") then
                if tonumber(p_t.value)>255 then
                        res = nil
                end
        end
        return res;
end
 
可以看到lua_protocol的方法做了一个字符串个匹配,找到”tcp“这个字符串,然后再查configs.lua中的表;这里用到了访问lua的table的一种方法,如
 local a = {};
a.k="hello"
a.k和a['k']都是可以正确访问的。
lua_protocol方法中表中原素是变量,所以可以用第二种访问表的方法取到值。
 
以下是C中调用lua的方式:
 
get_protocols函数实现了调用config.lua文件,返回从lua文件中获取传入的协议所对应的号码。
int get_protocols(lua_State *l, char * str)
{
        int dofile;
        int res;

        dofile = luaL_dofile(l, "lua_protocol.lua");

        if(dofile == 0){
                lua_getglobal(l, "lua_protocol");
                lua_pushstring(l, str);
                lua_call(l, 1, 1);

                res = lua_tonumber(l, -1);
                lua_pop(l, 1);
        }else{
                res = -1;
        }
        return res;
}
 
以上的函数中虚拟栈l实现了数据传递的功能,它是lua_State类型的;可以看到以上所用的所有lua的API函数都需要传入这个虚拟栈。
 luaL_dofile(l, "lua_protocol.lua"),dofile是解释并调用lua_pcall执行传入的lua文件,如果被正确执行返回0,否则返回非0值,且错误的消息被压入栈,可以通过访问栈顶来获取错误消息。
lua_getglobal(l, "lua_protocol"); 将lua_protocol方法压入栈中,因为之前的栈是空的,所以这个方法在栈底,也在目前的栈顶。
lua_pushstring(l, str); 将str作为lua_protocol的参数传递进去。
lua_call(l, 1, 1); 调用方法,这个函数需要传入虚拟栈,参数的个数,以及返回的结果的个数。
 res = lua_tonumber(l, -1); 从栈顶取得返回值
 lua_pop(l,1); 清空栈。
lua_pop的定义原型是:
#define lua_pop(L, n)    lua_settop(L, -(n)-1)
 lua_pop(l,1), 即把栈顶的指针指向了栈底
 
 
main函数中调用get_protocols方法之前需要打开lua的库,代码如下:

int main()
{
        int int_protocol;

        lua_State *L = luaL_newstate();
        luaL_openlibs(L);

        int_protocol = get_protocols(L, "protocol=TCP");
        if(int_protocol == -1){
                printf("param is not valid!\n");
        }else{
                printf("protocol is :%d\n", int_protocol);
        }

        lua_close(L);

        return 0;
}
 
最后需要关闭lua。
 
就这么简单!

转载于:https://www.cnblogs.com/mashiaoo/archive/2013/02/06/lua%e5%86%99C%e7%9a%84%e6%8f%92%e4%bb%b6.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值