欢迎来到飞鸟慕鱼博客,开始您的技术之旅!
当前位置: 首页知识笔记正文

Lua与C 交互,交互

终极管理员 知识笔记 77阅读

文章目录 1、Lua和C交互2、基础练习2.1、加载Lua脚本并传递参数2.2、加载脚本到stable包2.3、Lua调用c语言接口2.4、Lua实现面向对象2.5、向脚本中注册c的类

1、Lua和C交互

1、lua和c交互机制是基于一个虚拟栈C和lua之间的所有数据交互都通过这个虚拟栈来完成无论何时C想从lua中调用一个值被请求的值将会被压入栈C想要传递一个值给Lua首选将整个值压栈然后就可以在Lua中调用。
2、lua中提供正向和反向索引区别在于证书永远是栈底负数永远是栈顶。

2、基础练习

编译指令g test.cpp -o test -llua -ldl

#include <iostream>  #include <string.h>  using namespace std; extern C{#include lua.h  #include lauxlib.h  #include lualib.h  }// g test.cpp -o test  -llua -ldlint main(){//1.创建一个state  // luaL_newstate返回一个指向堆栈的指针lua_State *L  luaL_newstate(); //2.入栈操作  lua_pushstring(L, hello world);lua_pushnumber(L, 200); //3.取值操作  if (lua_isstring(L, 1)) {             //判断是否可以转为string  cout << lua_tostring(L, 1) << endl;  //转为string并返回  }if (lua_isnumber(L, 2)) {cout << lua_tonumber(L, 2) << endl;} //4.关闭state  lua_close(L);return 0;}
2.1、加载Lua脚本并传递参数

编译指令g test.cpp -o test -llua -ldl

函数说明1、函数用于将Lua脚本加载到Lua虚拟机中并进行编译luaL_loadbuffer(L,s,sz,n)lua_State *LLua状态对象表示Lua虚拟机的运行实例。const char *buff指向Lua脚本内容的字符串。size_t szLua脚本内容的长度。const char *name可选参数用于给脚本设置一个名称便于调试和错误消息的输出。返回值不为0表示有错误2、函数用于调用Lua函数并处理其执行过程中可能发生的错误lua_pcall(L,n,r,f)lua_State *LLua状态对象表示Lua虚拟机的运行实例。int nargs传递给Lua函数的参数数量。int nresults期望的返回值数量。int errfunc错误处理函数在调用栈中的索引。返回值不为0表示有错误3、函数用于从全局环境中获取一个全局变量并将其值压入Lua栈顶int lua_getglobal(lua_State *L, const char *name)lua_State *LLua状态对象表示Lua虚拟机的运行实例。const char *name要获取的全局变量的名称。4、函数用于将一个数字lua_Number类型压入Lua栈顶void lua_pushnumber(lua_State *L, lua_Number n)lua_State *LLua状态对象表示Lua虚拟机的运行实例。lua_Number n要压入栈的数字。

执行流程
1、加载script脚本加载到lua虚拟机中
2、将脚本中的my_pow函数压入到栈顶
3、压入my_pow需要的两个参数
4、执行脚本
5、获取脚本中的返回值

#include <cstdio>#include <cstring>#include <cmath>#include <new>extern C {    #include <lua.h>    #include <lualib.h>    #include <lauxlib.h>}char const *script  R(function hello()    print(hello world)endfunction my_pow(x,y)    return x^yend);char const *script_1  R(    pkg.hello());int main(){    /*        加载脚本并传递参数    */        // 创建lua虚拟机创建虚拟栈    lua_State *state  luaL_newstate();    // 打开lua标准库以便正常使用lua api    luaL_openlibs(state);    {        // 将lua脚本加载到虚拟机中并编译        auto rst  luaL_loadbuffer(state,script,strlen(script),hello);        // 判断是否加载成功        if(rst !0 ){            if(lua_isstring(state,-1)){                auto msg  lua_tostring(state,-1);                printf(load script faile:%s\n,msg);                lua_pop(state,-1);            }            return -1;        }        // 执行加载并编译的Lua脚本        if(lua_pcall(state,0,0,0)){            if(lua_isstring(state,-1)){                auto msg  lua_tostring(state,-1);                printf(load script faile:%s,msg);                lua_pop(state,-1);            }        }        // 从全局环境中获取一个my_pow函数压入到栈顶        lua_getglobal(state,my_pow);        // 判断栈顶是不是一个函数要是不是表示没有找到        if(!lua_isfunction(state,-1)){            printf(function  named my_pow not function\n);            return -1;        }        // 将数字参数压入Lua栈中        lua_pushnumber(state,2);        lua_pushnumber(state,8);        rst  lua_pcall(state,2,1,0);        if(rst !0 ){            if(lua_isstring(state,-1)){                auto msg  lua_tostring(state,-1);                printf(load script faile:%s\n,msg);                lua_pop(state,-1);            }            return -1;        }        if(lua_isnumber(state,-1)){            lua_Number val  lua_tonumber(state,-1);            printf(%lf\n,val);        }    }    lua_close(state);    return 0;}
2.2、加载脚本到stable包

编译命令 g main.cpp -o main -llua -ldl

#include <cstdio>#include <cstring>#include <cmath>#include <new>extern C {    #include <lua.h>    #include <lualib.h>    #include <lauxlib.h>}char const *script  R(function hello()    print(hello world)endfunction my_pow(x,y)    return x^yend);/*   _G  {    helloworld  function print(hello world)    }    _G  {        pkg  {            helloworld  function print(hello world)        }    }    pkg.helloworld()*/    char const *script_1  R(    pkg.hello());int main(){    /*        加载脚本到stable包        1、生成chunk push到栈顶        2、创建table设置给_G表_G[pkg]  {}        3、给这个table设置元表元表继承_G的访问域(__index)        4、执行code chunk    */    lua_State *state  luaL_newstate();    luaL_openlibs(state);    {        auto rst  luaL_loadbuffer(state,script,strlen(script),helloworld);        if(rst ! 0){            if(lua_isstring(state,-1)){                auto msg  lua_tostring(state,-1);                printf(load script faile:%s\n,msg);                lua_pop(state,1);            }            return -1;        }                // 取出_G表        lua_getglobal(state,_G);        if(lua_istable(state,-1)){  // chunk _G            lua_newtable(state);    // 创建表 chunk _G new_stable            lua_pushstring(state,pkg); // chunk _G new_stable pkg            lua_pushvalue(state,-2); // chunk _G new_stable pkg new_stable            lua_rawset(state,-4);   // chunk _G new_stable            char const *upvalueName  lua_setupvalue(state,-3,1); // chunk _G            lua_newtable(state);    // chunk _G metastable            lua_pushstring(state,__index);    // chunk _G metastable __index            lua_pushvalue(state,-3); // chunk _G metastable __index _G            lua_rawset(state,-3);   // chunk _G metastable            lua_pushstring(state,pkg);            lua_rawget(state,-3);   // chunk _G metastable pkg(table)            lua_pushvalue(state,-2);    // chunk _G metastable pkg(table) metastable            lua_setmetatable(state,-2); // chunk _G metastable pkg(stable)            lua_pop(state,3);   // chunk        }        // 执行chunk        if(lua_pcall(state,0,0,0)){            if(lua_isstring(state,-1)){                auto msg  lua_tostring(state,-1);                printf(call function chunk failed:%s\n,msg);                lua_pop(state,1);            }        }        // 加载script_1        rst  luaL_loadbuffer(state,script_1,strlen(script_1),script_1);        if(rst ! 0){            if(lua_isstring(state,-1)){                auto msg  lua_tostring(state,-1);                printf(load script failed:%s\n,msg);                lua_pop(state,1);            }            return -1;        }        if(lua_pcall(state,0,0,0)){            if(lua_isstring(state,-1)){                auto msg  lua_tostring(state,-1);                printf(call function chunk failed:%s\n,msg);                lua_pop(state,1);            }        }        lua_close(state);    }    return 0;}
2.3、Lua调用c语言接口
#include <cstdio>#include <cstring>#include <cmath>#include <new>extern C {    #include <lua.h>    #include <lualib.h>    #include <lauxlib.h>}int pow_from_c(lua_State *L){    int param_count  lua_gettop(L);    if(param_count ! 2)        return 0;        if(lua_isinteger(L,1) && lua_isinteger(L,2)){        auto x  lua_tointeger(L,1);        auto y  lua_tointeger(L,2);        int rst  (int)pow(x,y);        lua_pushinteger(L,rst);        return 1;    }    return 0;}char const *script_2  R(    local val  pow_from_c(2,3)    print(val));int main(){    // lua调用c语言接口    lua_State *state  luaL_newstate();    luaL_openlibs(state);    {        /*            _G  {                pow_from_c  pow_from_c            }        */        lua_getglobal(state,_G);        lua_pushstring(state,pow_from_c);        lua_pushcclosure(state,pow_from_c,0);    // _G pow_from_c; closure        lua_rawset(state,-3);   // _G        lua_pop(state,1);   // _G    }    auto rst  luaL_loadbuffer(state,script_2,strlen(script_2),script_2);    if(rst ! 0){        if(lua_isstring(state,-1)){            auto msg  lua_tostring(state,-1);            printf(load script faile:%s\n,msg);            lua_pop(state,1);        }        return -1;    }    if(lua_pcall(state,0,0,0)){        if(lua_isstring(state,-1)){            auto msg  lua_tostring(state,-1);            printf(call function chunk failed:%s\n,msg);            lua_pop(state,1);        }    }    lua_close(state);    return 0;}
2.4、Lua实现面向对象
local anial_matestable  {    __index  {        walk  function (self)            print(self,我是walk)        end,        eat  function (self)            print(self,eat.)        end,    },    __newindex  function (object,key,value)        print(assigned ..value..named ..key..but not really)    end,}function newobject()    local objs  {name  xxxx}    setmetatable(objs,anial_matestable)    return objsendlocal obj  newobject()obj.eat()obj.walk()obj.name  abcobj.id  0
2.5、向脚本中注册c的类
#include <cstdio>#include <cstring>#include <cmath>#include <new>extern C {    #include <lua.h>    #include <lualib.h>    #include <lauxlib.h>}char const *script_3  R(    local obj_1  create_game_object(1);    local obj_2  create_game_object(1);    local obj_3  create_game_object(2);    local rst1  obj_1:equal(obj_2)    local rst2  obj_1:equal(obj_3)    print(rst1,;,rst2)    print(..obj_1:id()));class GameObject{private:    u_int32_t _id;public:    static size_t registy_value;public:    GameObject(u_int32_t id):_id(id)    {}    u_int32_t id()const{        return _id;    }    bool equal(GameObject *obj){        return _id  obj->id();    }};size_t GameObject::registy_value  0;int GameObject_equal(lua_State *state){    int arg_count  lua_gettop(state);    if(arg_count!2){        return 0;    }    if(lua_isuserdata(state,1) && lua_isuserdata(state,2)){        void *userdata_self  lua_touserdata(state,1);        void *userdata_that  lua_touserdata(state,2);        GameObject *obj1  (GameObject*)userdata_self;        GameObject *obj2  (GameObject*)userdata_that;        auto rst  obj1->equal(obj2);        lua_pushboolean(state,rst);        return 1;    }    return 0;}int GameObject_id(lua_State* state){    GameObject *this_obj  (GameObject*)lua_touserdata(state,1);    auto rst  this_obj->id();    lua_pushinteger(state,rst);    return 1;}int create_game_object(lua_State* state){    auto id  lua_tointeger(state,1);    void *p  lua_newuserdata(state,sizeof(GameObject));    GameObject *obj  new(p)GameObject(id);    lua_rawgetp(state,LUA_REGISTRYINDEX,&GameObject::registy_value);    lua_setmetatable(state,-2);    return 1;}int main(){    // 怎么向脚本中注册c的类    // 使用userdata    /*        userdata:{            metadata:{                __index  {                    equal  function(){},                    id  function(){},                }            }        }    */    lua_State *state  luaL_newstate();    luaL_openlibs(state);    {        lua_getglobal(state,_G);        lua_pushstring(state,create_game_object);        lua_pushcclosure(state,create_game_object,0);        lua_rawset(state,-3);        lua_pop(state,1);        lua_newtable(state);        lua_pushstring(state,__index);        lua_newtable(state);        lua_pushstring(state,equal);        lua_pushcclosure(state,GameObject_equal,0);        lua_rawset(state,-3);        lua_pushstring(state,id);        lua_pushcclosure(state,GameObject_id,0);        lua_rawset(state,-3);        lua_rawset(state,-3);        lua_rawsetp(state,LUA_REGISTRYINDEX,&GameObject::registy_value);        auto rst  luaL_loadbuffer(state,script_3,strlen(script_3),oop);        if(rst ! 0){            if(lua_isstring(state,-1)){                auto msg  lua_tostring(state,-1);                printf(load script failed:%s\n,msg);                lua_pop(state,1);            }            return -1;        }        // 执行        if(lua_pcall(state,0,0,0)){            if(lua_isstring(state,-1)){                auto msg  lua_tostring(state,-1);                printf(load script failed:%s\n,msg);                lua_pop(state,1);            }        }    }    lua_close(state);    return 0;}

标签:
声明:无特别说明,转载请标明本文来源!