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中提供正向和反向索引区别在于证书永远是栈底负数永远是栈顶。
编译指令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;}
标签: