Lua5.3 与C交互学习
2015-10-07 16:57
549 查看
C++调用Lua函数
main函数中环境搭建下载lua5.3.1 tar.gz
创建控制台项目, 静态库, 取消预编译头;
C/C++>常规>附加包含目录: 加入5.3.1\src
编译得到lublib.lib
创建新工程
在vc++目录里添加包含目录 和库目录;
连接器里添加lualib.lib
编译; 如果失败则拷贝lualib.lib到根目录dubug下;
OK
[code]#include <stdio.h> #include <string.h> extern "C" { #include <lua.h> #include <lualib.h> #include <lauxlib.h> } int main(int argc, char* argv[]) { lua_State *L = luaL_newstate(); luaL_openlibs(L); // 加载Lua通用扩展库 if(luaL_loadfile(L,"test.lua"||lua_pcall(L,0,0,0)) //或luaL_dofile(L,"test.lua") printf("error pcall!: %s\n",lua_tostring(L,-1)); // 前面搭建了运行环境,lua代码写在了test.lua文件中 // ...... // lua_close(L); return 0; }
要在C++中调用lua函数,则有如下函数可以利用:
lua_getglobal()就是从lua中取得函数,压入栈中;随后压入函数的参数;
如在test.lua中有如下代码:
[code]function he(x,y) return x*y end
则的C++中的调用过程是:
[code]//..... lua_getgloabl(L,"he"); lua_pushnumber(L,5); lua_pushnumber(L,6); // run the lua program // lua_pcall(L,nargs,nresults,0) if(lua_pcall(L,2,1,0) != 0) printf("error pcall!: %s\n",lua_tostring(L,-1)); // if error then push errorinfo in the stack else push reuslts if(!lua_isnumber(L,-1)) printf("error return!\n"); int re = (int)lua_tonumber(L,-1);
函数参数、返回值压栈是正序压栈;如果有错误发生的话, lua_pcall 会捕获它,然后把单一的值(错误信息)压入堆栈,然后返回错误码。lua_pcall 总是把函数本身和它的参数从栈上移除。
Lua中调用C++函数
要写一个能让Lua调用的C函数,就要符合lua_CFunction定义:typedef int (*lua_CFunction) (lua_State *L); //return 返回值的个数
当Lua调用C函数的时候,同样使用栈来交互。C函数从栈中获取她的参数,调用结束后将结果放到栈中,并返回放到栈中的结果个数。
这儿有一个重要的概念:用来交互的栈不是全局栈,每一个C函数都有他自己的私有栈。当Lua调用C函数的时候,第一个参数总是在这个私有栈的index=1的位置。
如:函数he
[code] static int he(lua_State* L) { // 从栈中检查参数是否合法并读取参数, int a = luaL_checknumber(L,1); int b = luaL_checknumber(L,2); int re = a*b; // 将运算结果返回栈中供lua使用 lua_pushnumber(L,re); return 1; }
在mai中,可以使用
lua_dostring(),lua_loadfile()||lua_pcall(L,0,0,0)来执行lua代码:
[code]int main(int argc, char* argv[]) { lua_State *L = luaL_newstate(); luaL_openlibs(L); // 加载Lua通用扩展库 // 将he函数注册成lua的全局函数 lua_register(L,"he",he); if(luaL_loadfile(L,"test.lua")/*||lua_pcall(L,0,0,0)*/) printf("error pcall!: %s\n",lua_tostring(L,-1)); lua_close(L); return 0; }
.lua文间之间的全局变量调用
比如有两个文件[code]//a.lua a = 50 local b = 10
[code]//h.lua dofile("X:/.../a.lua") //或在同一个目录下时:doflie("a.lua") print(a,b)
lua中:
直接运行h.lua想要调用a.lua中的内容则要在a.lua中运行
dofile("X:/.../a.lua")
C++中两种方法:
- 如上面所示, 在h.lua中使用dofile(“a.lua”), 文件放同一个目录;
- 或在C代码加载时先用luaL_dofile(L,”a.lua”); 再luaL_dofile(L,”h.lua”); 顺序不能变;
引入C模块到 lua
luaL_register,这个函数接收一些C函数及其名称,并将这些函数注册到一个与模块同名的table中假设创建一个模块,其中包含了这个luaglue函数。首先,必须定义这个模块函数:
[code]static int luaglue(lua_state *L) { }
然后,声明一个数组,其中包含模块中所有函数及名称。这个数组元素的类型为luaL_Reg结构,该结构有两个字段,一个字符串和一个函数指针:
[code]static const struct luaL_Reg mylib[] = { {"dir",l_dir}, {NULL,NULL}//结尾 };
最后,声明一个主函数,其中用到了luaL_register:
[code]int luaopen_mylib(lua_State *L) { luaL_register(L,"mylib",mylib); return 1; }
其中luaL_register原型为:
void luaL_register (lua_State *L,const char *libname,const luaL_Reg *l);
luaL_register根据给定的名称(“mylib”)创建(或复用)一个table,并用数组mylib中的信息填充这个table。在luaL_Register返回时,会将这个table留在栈中。最后,luaopen_mylib函数返回1,表示将这个table返回给Lua。
ps:打开一个库,当libname为null时,该函数注册所有在luaL_Reg上的函数,不为null时,该函数会创建一个table,根据libname注册不与libname关联的函数。
当写完c模块后,必须将其链接到解释器。如果Lua解释器支持动态链接的话,那么最简便的方法是使用动态链接机制。在这种情况中,必须将c代码编译成动态链接库,并将这个库放入C路径(LUA_CPATH)中。然后,便可以用require从Lua中加载这个模块:
[code]require "mylib"
这名调用会将动态库mylib链接到Lua,并会寻找luaopen_mylib函数,将其注册为一个Lua函数,然后调用它以打开模块。
如果解释器不支持动态链接,那么就必须用新的模块来重新编译Lua。此外,还需要以某种方式来告诉解释器,它应在打开一个新状态的同时打开这个模块。最简单的做法是,将luaopen_mylib加到luaL_openlibs会打开的标准库列表中,这个列表在文件linit.c中。
从C++程序员的观点来看,Lua像一个“黑盒子”,为一些服务处理命令和调用。Lua通常作为最上层接口直接和程序使用者和游戏玩家打交道,在核心程序处理之前接受并响应输入。
lua5.3 C++注册函数或模块到lua
上面的那个luaL_register函数在lua5.2以后就没有用了,所以一直在找5.2以后版本的用法, 网上找了半天都没有指出重点,最后在下面的网站上找到;http://acamara.es/blog/2012/08/passing-variables-from-lua-5-2-to-c-and-vice-versa/
结合下面两篇介绍后这里给出一些理解:
http://www.linuxidc.com/Linux/2014-05/102528p2.htm
http://blog.163.com/cqit_jsj/blog/static/65127220127251231881/
[code]//要注册的lua里的C++函数的写法这里就不说了,随便写一个 static int f(lua_State* L) { printf("hello\n"); return 0; } // .... 还可以继续添加 //注册函数数组 const luaL_Reg mylib[] = { {"myf",f}, //{//可以继续添加}, {NULL,NULL} } //定义一个库打开函数 static luaopen_mylib(lua_State* L) { //lua5.1 是luaL_register(L,"mylib",mylib)来完成 // lua5.2以上是 lua_newlib(L,mylib); //或者等效为下面 luaL_newlibtable(L,mylib); lubL_setfuncs(L,func,0); return 1; } //如果有多个库可以在用个库数组来进行注册如下 // 可不用 const luaL_Reg lualibs[]= { {"mylib",luaopen_func}, //打开库函数 {/*其它库*/}, {NULL,NULL}, } // 到这里,我们可以选择去将库导出为.dll来在lua中调用,这个网上好多资料,在lua中要用local mylib = require "mylib"来获取.dll文件, 参考 http://blog.csdn.net/ljhjason/article/details/28860633 //这里选择不导出为.dll所以进行如下操作: int main { lua_State* L = luaL_newstate(); luaL_openlibs(L); // 打开自己的库如果用了lublibs库数组则用循环打开 luaL_requiref(L,"mylib",luaopen_mylib,1); lua_pop(L,1); luaL_dofile("xxx.lua"); .... }
注册C++类到lua
/article/1594738.html相关文章推荐
- lua类
- Lua学习之Lua的函数解析(待补充)
- coroutine in lua
- Lua学习之xcode下简单调用C语言函数(待补充)
- Lua入门基础
- LintCode "Expression Evaluation"
- lua快速入门[转]
- Lua: Good, bad, and ugly parts
- UVALive 6697 Homework Evaluation
- Java Evaluate Reverse Polish Notation(逆波兰式)
- 为什么要用Lua脚本呢?(一)
- 150. Evaluate Reverse Polish Notation (Stack)
- lua脚本的基本语法(二)
- ubuntu15.04编译lua源码
- lua.c:80:31: fatal error: readline/readline.h: No such file or directory
- Lua错误:nesting of [[...]] is deprecated near '['
- 逻辑操作符---Lua: and,or,not 对比 C++:&&,||,!
- lua转让C++书面DLL达到“热更新”
- lua userdata
- lua-epoll 模块简单分析