• lua和c的交互


    1. extern "C" {
    2. #include "lua.h"
    3. #include "lualib.h"
    4. #include "lauxlib.h"
    5. }
    6.  
    7. #include <iostream>
    8. #include <string>
    9. using namespace std;
    10.     
    11. int main()
    12. {
    13.     //Lua示例代码
    14.     char *szLua_code =
    15.         "r = string.gsub(c_Str, c_Mode, c_Tag) --宿主给的变量 "
    16.         "u = string.upper(r)";
    17.     //Lua的字符串模式
    18.     char *szMode = "(%w+)%s*=%s*(%w+)";
    19.     //要处理的字符串
    20.     char *szStr = "key1 = value1 key2 = value2";
    21.     //目标字符串模式
    22.     char *szTag = "<%1>%2</%1>";
    23.  
    24.     lua_State *L = luaL_newstate();
    25.     luaL_openlibs(L);
    26.  
    27.     //把一个数据送给Lua
    28.     lua_pushstring(L, szMode);
    29.     lua_setglobal(L, "c_Mode");
    30.     lua_pushstring(L, szTag);
    31.     lua_setglobal(L, "c_Tag");
    32.     lua_pushstring(L, szStr);
    33.     lua_setglobal(L, "c_Str");
    34.  
    35.     //执行
    36.     bool err = luaL_loadbuffer(L, szLua_code, strlen(szLua_code),
    37.                 "demo") || lua_pcall(L, 0, 0, 0);
    38.     if(err)
    39.     {
    40.         //如果错误,显示
    41.         cerr << lua_tostring(L, -1);
    42.         //弹出栈顶的这个错误信息
    43.         lua_pop(L, 1);
    44.     }
    45.     else
    46.     {
    47.         //Lua执行后取得全局变量的值
    48.         lua_getglobal(L, "r");
    49.         cout << "r = " << lua_tostring(L,-1) << endl;
    50.         lua_pop(L, 1);
    51.         
    52.         lua_getglobal(L, "u");
    53.         cout << "u = " << lua_tostring(L,-1) << endl;    
    54.         lua_pop(L, 1);
    55.     }
    56.     lua_close(L);
    57.     return 0;
    58. }


        这段代码把字符串中的key=value字符串全部转换成XML格式<key>value</key>
        在这个例子中,C++程序通过调用lua_pushstring把C字符串压入栈顶,lua_setglobal的作用是把栈顶的数据传到Lua环境中作为全局变量。
        执行代码完成后,使用lua_getglobal从Lua环境中取得全局变量压入栈顶,然后使用lua_tostring把栈顶的数据转成字符串。由于lua_tostring本身没有出栈功能,所以为了平衡(即调用前与调用后栈里的数据量不变),使用lua_pop弹出由lua_setglobal压入的数据。
        从上面的例子可以看出,C++和Lua之间一直围绕着栈在转,可见栈是极为重要的。有必要列出一些Lua C API中的主要栈操作先,它们的作用直接可以从函数名中看出。
    压入元素到栈里

    void lua_pushnil (lua_State *L);    
    void lua_pushboolean (lua_State *L, int bool);
    void lua_pushnumber (lua_State *L, double n);
    void lua_pushlstring (lua_State *L, const char *s, size_t length);
    void lua_pushstring (lua_State *L, const char *s);
    void lua_pushcfunction (lua_State *L, lua_CFunction fn);


    查询栈里的元素

    lua_isnil (lua_State *L, int index);
    lua_isboolean (lua_State *L, int index);
    int lua_isnumber (lua_State *L, int index);
    int lua_isstring (lua_State *L, int index);
    int lua_isfunction (lua_State *L, int index);
    int lua_istable (lua_State *L, int index);
    int lua_isuserdata (lua_State *L, int index);
    lua_islightuserdata (lua_State *L, int index);
    lua_isthread (lua_State *L, int index);

     

    转换栈里的元素

    int                lua_toboolean (lua_State *L, int index);
    double            lua_tonumber (lua_State *L, int index);
    const char *    lua_tostring (lua_State *L, int index);
    const char *    lua_tolstring (lua_State *L, int idx, size_t *len);
    size_t            lua_strlen (lua_State *L, int index);
    lua_CFunction   lua_tocfunction (lua_State *L, int idx);
    void *          lua_touserdata (lua_State *L, int idx);
    lua_State *     lua_tothread (lua_State *L, int idx);

     

    Lua栈的维护

    int  lua_gettop (lua_State *L);
        取得栈顶元素的索引,即栈中元素的个数
    void lua_settop (lua_State *L, int index);
        设置栈顶索引,即设置栈中元素的个数,如果index<0,则从栈顶往下数,下同
    void lua_pushvalue (lua_State *L, int index);
        把栈中指定索引的元素复制一份到栈顶
    void lua_remove (lua_State *L, int index);
        删除指定索引的元素
    void lua_insert (lua_State *L, int index);
        移动栈顶元素到指定索引的位置,栈中数目没有改变
    void lua_replace (lua_State *L, int index);
        从栈顶弹出元素值并将其设置到指定索引位置,栈中的数目减一
    int  lua_checkstack (lua_State *L, int extra);
        确保堆栈上至少有 extra 个空位。如果不能把堆栈扩展到相应的尺寸,函数返回 false 。这个函数永远不会缩小堆栈。
    int  lua_pop(L,n)
        从栈顶弹出n个元素,它是一个lua_settop的包装:#define lua_pop(L,n)  lua_settop(L, -(n)-1)

     

    表的操作
    上面的列表中并没有lua_pushtable和lua_totable,那么怎样取得或设置Lua中的table数据呢?
    在Lua中,table是一个很重要的数据类型,在table中不仅可以象C中的数据一样放一组数据,还可以象map一样以key=value的方式存放数据,如Lua代码中的:

    tb = {"abc",12,true,x=10,y=20,z=30}

        前三个数据可以用tb[1]~tb[3]取得
        而后三个数据通过tb.x, tb.y, tb.z取得
    尽管看起来很牛叉,不过剥开神奇的外衣,实际上Lua的table中,所有的数据都是以key=value的形式存放的,这句Lua代码也可以写成:

    tb = {[1]="abc", [2]=12, [3] = true, ["x"]=10, ["y"]=20, ["z"]=30}

        它的形式就是[key]=value,所谓的tb.x只是tb["x"]的语法糖而已,如果愿意,也可以用tb["x"]取得这个数据10。
    我们把上面的例子改成使用表的

    1. ...
    2. int main()
    3. {
    4.     //Lua示例代码,使用table
    5.     char *szLua_code =
    6.         "x = {} --用于存放结果的table "
    7.         "x[1],x[2] = string.gsub(c.Str, c.Mode, c.Tag) --x[1]里是结果,x[2]里是替换次数 "
    8.         "x.u = string.upper(x[1])";
    9.     //Lua的字符串模式
    10.     char *szMode = "(%w+)%s*=%s*(%w+)";
    11.     //要处理的字符串
    12.     char *szStr = "key1 = value1 key2 = value2";
    13.     //目标字符串模式
    14.     char *szTag = "<%1>%2</%1>";
    15.  
    16.     lua_State *L = luaL_newstate();
    17.     luaL_openlibs(L);
    18.  
    19.     //把一个tabele送给Lua
    20.     lua_newtable(L);    //新建一个table并压入栈顶
    21.     lua_pushstring(L, "Mode");// key
    22.     lua_pushstring(L, szMode);// value
    23.     //设置newtable[Mode]=szMode
    24.     //由于上面两次压栈,现在table元素排在栈顶往下数第三的位置
    25.     lua_settable(L, -3);
    26.     //lua_settable会自己弹出上面压入的key和value
    27.  
    28.     lua_pushstring(L, "Tag");// key
    29.     lua_pushstring(L, szTag);// value
    30.     lua_settable(L, -3);    //设置newtable[Tag]=szTag
    31.  
    32.     lua_pushstring(L, "Str");// key
    33.     lua_pushstring(L, szStr);// value
    34.     lua_settable(L, -3);    //设置newtable[Str]=szStr
    35.  
    36.     lua_setglobal(L,"c"); //将栈顶元素(newtable)置为Lua中的全局变量c
    37.  
    38.     //执行
    39.     bool err = luaL_loadbuffer(L, szLua_code, strlen(szLua_code),
    40.                 "demo") || lua_pcall(L, 0, 0, 0);
    41.     if(err)
    42.     {
    43.         //如果错误,显示
    44.         cerr << lua_tostring(L, -1);
    45.         //弹出栈顶的这个错误信息
    46.         lua_pop(L, 1);
    47.     }
    48.     else
    49.     {
    50.         //Lua执行后取得全局变量的值
    51.         lua_getglobal(L, "x");
    52.  
    53.         //这个x应该是个table
    54.         if(lua_istable(L,-1))
    55.         {
    56.             //取得x.u,即x["u"]
    57.             lua_pushstring(L,"u");    //key
    58.             //由于这次压栈,x处于栈顶第二位置
    59.             lua_gettable(L,-2);
    60.             //lua_gettable会弹出上面压入的key,然后把对应的value压入
    61.             //取得数据,然后从栈中弹出这个value
    62.             cout << "x.u = " << lua_tostring(L,-1) << endl;
    63.             lua_pop(L, 1);
    64.             
    65.             //取得x[1]和x[2]
    66.             for(int i=1; i<=2; i++)
    67.             {
    68.                 //除了key是数字外,与上面的没什么区别
    69.                 lua_pushnumber(L,i);
    70.                 lua_gettable(L,-2);
    71.                 cout << "x[" << i <<"] = " << lua_tostring(L,-1) << endl;
    72.                 lua_pop(L, 1);
    73.             }
    74.         }
    75.  
    76.         //弹出栈顶的x
    77.         lua_pop(L, 1);
    78.     }
    79.     lua_close(L);
    80.     return 0;
    81. }

    本例中用到的新Lua C API是:

    void lua_newtable (lua_State *L);
        新建一个空的table并压入栈顶。
    void lua_settable (lua_State *L, int idx);
        lua_settable以table在栈中的索引作为参数,并将栈顶的key和value出栈,用这两个值修改table。
    void lua_gettable (lua_State *L, int idx);
        lua_gettable以table在栈中的索引作为参数,弹出栈顶的元素作为key,返回与key对应的value并压入栈顶。
    最后,Lua告别针对table提供了存取函数
    void lua_rawgeti (lua_State *L, int idx, int n)
        取得table[n]并放到栈顶,上例中69-70行的lua_pushnumber(L,i);lua_gettable(L,-2);可以用lua_rawgeti(L,-1)代替。
    lua_getfield (lua_State *L, int idx, const char *k)
        取得table.k并放到栈顶,上例中57-59行的lua_pushstring(L,"u");lua_gettable(L,-2);可以替换成lua_getfield(L,-1,"u")。
    void lua_setfield (lua_State *L, int idx, const char *k)
        把栈顶的数据作为value放入table.k中,上例中的形如lua_pushstring(L, "key");lua_pushstring(L, value);lua_settable(L, -3);可以改成lua_pushstring(L, value);lua_setfield(L,-2,"key");的形式。
    void lua_rawseti (lua_State *L, int idx, int n)
        把栈顶的数据作为value放入table[n]中
    
    
    http://blog.csdn.net/zhangjingyangguang/article/details/5221691
    
  • 相关阅读:
    如何用纯 CSS 创作一个蝴蝶标本展示框
    如何用纯 CSS 创作一个菱形 loader 动画
    如何用纯 CSS 创作背景色块变换的按钮特效
    如何用纯 CSS 绘制一个充满动感的 Vue logo
    css实现盒尺寸重置、均匀分布的子元素、截断文本
    Wireshark分析RabbitMQ
    MVC5 一套Action的登录控制流程
    MySQL timespan设置 sql_mode设置
    MVC webapi,Action的分别拦截器
    CentOS7.2 安装RabbitMQ3.6.10
  • 原文地址:https://www.cnblogs.com/byfei/p/14104386.html
Copyright © 2020-2023  润新知