设为首页 加入收藏

TOP

Lua和C++交互总结(很详细)(一)
2015-07-20 17:44:14 来源: 作者: 【 】 浏览:4
Tags:Lua 交互 总结 详细

?

一不小心又标题党了?不好意思哈~

翻看了以前的博客,发下废话太多了自己都看不下去啊,恩,以后尽量写得简洁一些。

?

本文不涉及lua语法学习,如果有需要,请移步:http://book.luaer.cn/

?

一.lua堆栈

?

要理解lua和c++交互,首先要理解lua堆栈。

?

简单来说,Lua和C/c++语言通信的主要方法是一个无处不在的虚拟栈。栈的特点是先进后出。

在lua中,lua堆栈就是一个struct,堆栈索引的方式可是是正数也可以是负数,区别是:正数索引1永远表示栈底,负数索引-1永远表示栈顶。如图:

\

?

二.堆栈的操作

?

因为lua与c/c++是通过栈来通信,lua提供了C API对栈进行操作。

我们先来看一个最简单的例子:

?

?

#include 
  
   
#include 
   
     using namespace std; extern C { #include lua.h #include lauxlib.h #include lualib.h } void main() { //1.创建一个state lua_State *L = luaL_newstate(); //2.入栈操作 lua_pushstring(L, I am so cool~); lua_pushnumber(L,20); //3.取值操作 if( lua_isstring(L,1)){ //判断是否可以转为string cout<
    
     

?

?

可以简单理解为luaL_newstate返回一个指向堆栈的指针,其它看注释应该能懂了吧。

如果对extern C不熟悉的可以点击这里:http://blog.csdn.net/shun_fzll/article/details/39078971。

?

其他一些栈操作:

?

?

int   lua_gettop (lua_State *L);			//返回栈顶索引(即栈长度)
void  lua_settop (lua_State *L, int idx);	//				
void  lua_pushvalue (lua_State *L, int idx);//将idx索引上的值的副本压入栈顶
void  lua_remove (lua_State *L, int idx);	//移除idx索引上的值
void  lua_insert (lua_State *L, int idx);	//弹出栈顶元素,并插入索引idx位置
void  lua_replace (lua_State *L, int idx);	//弹出栈顶元素,并替换索引idx位置的值

?

?

lua_settop将栈顶设置为一个指定的位置,即修改栈中元素的数量。如果值比原栈顶高,则高的部分nil补足,如果值比原栈低,则原栈高出的部分舍弃。

所以可以用lua_settop(0)来清空栈。

?

三.c++调用lua


我们经常可以使用lua文件来作配置文件。类似ini,xml等文件配置信息。
现在我们来使用c++来读取lua文件中的变量,table,函数。


现在有这样一个hello.lua 文件:

?

str = I am so cool
tbl = {name = shun, id = 20114442}
function add(a,b)
	return a + b
end

?

?

我们写一个test.cpp来读取它:

?

#include 
      
       
#include 
       
         using namespace std; extern C { #include lua.h #include lauxlib.h #include lualib.h } void main() { //1.创建Lua状态 lua_State *L = luaL_newstate(); if (L == NULL) { return ; } //2.加载lua文件 int bRet = luaL_loadfile(L,hello.lua); if(bRet) { cout<
        
         

?

?

知道怎么读取后,我们来看下如何修改上面代码中table的值:

?

?

// 将需要设置的值设置到栈中
lua_pushstring(L, 我是一个大帅锅~);
// 将这个值设置到table中(此时tbl在栈的位置为2)
lua_setfield(L, 2, name);

?

?

我们还可以新建一个table:

?

?

// 创建一个新的table,并压入栈
lua_newtable(L);
// 往table中设置值
lua_pushstring(L, Give me a girl friend !); //将值压入栈
lua_setfield(L, -2, str); //将值设置到table中,并将Give me a girl friend 出栈

?

?

需要注意的是:堆栈操作是基于栈顶的,就是说它只会去操作栈顶的值。


举个比较简单的例子,函数调用流程是先将函数入栈,参数入栈,然后用lua_pcall调用函数,此时栈顶为参数,栈底为函数,所以栈过程大致会是:参数出栈->保存参数->参数出栈->保存参数->函数出栈->调用函数->返回结果入栈。

类似的还有lua_setfield,设置一个表的值,肯定要先将值出栈,保存,再去找表的位置。


再不理解可看如下例子:
?

lua_getglobal(L, add);		// 获取函数,压入栈中
lua_pushnumber(L, 10);			// 压入第一个参数
lua_pushnumber(L, 20);			// 压入第二个参数
int iRet= lua_pcall(L, 2, 1, 0);// 将2个参数出栈,函数出栈,压入函数返回结果

lua_pushstring(L, 我是一个大帅锅~);  // 
lua_setfield(L, 2, name);             // 会将我是一个大帅锅~出栈

另外补充一下:

?

lua_getglobal(L,var)会执行两步操作:1.将var放入栈中,2.由lua去寻找变量var的值,并将变量var的值返回栈顶(替换var)。
lua_getfield(L,-1,name) 的作用等价于 lua_pushstring(L,name) + lua_gettable(L,-2)

?

四.lua调用c++

?

我们分三个方法实现它。

?

方法一:直接将模块写入lua源码


在lua中调用c/c++,我们可以将函数写lua.c中,然后重新编译lua文件。
也许你用的是lua for windows集成环境,没关系,不会编译lua可以参考这篇:http://blog.csdn.net/snlscript/article/details/15533373


编译好后是这样子的:(如图)

?

\

?

然后我们可以在lua.c中加入我们自己的函数。函数要遵循规范(可在lua.h中查看)如下:

?

?

typedef int (*lua_CFunction) (lua_State *L);

?

?

换句话说,所有的函数必须接收一个lua_State作为参数,同时返回一个整数值。因为这个函数使用Lua栈作为参数,所以它可以从栈里面读取任意数量和任意类型的参数。而这个函数的返回值则表示函数返回时有多少返回值被压入Lua栈。(因为Lua的函数是可以返回多个值的)


然后我们在lua.c中加入如下函数:

?

// This is my function
static int getTwoVar(lua_State *L)
{
    // 向函数栈中压入2个值
    l
首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇The Himalayas(ZOJ) 下一篇Leetcode 栈 Valid Parentheses

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·C++中智能指针的性能 (2025-12-25 03:49:29)
·如何用智能指针实现c (2025-12-25 03:49:27)
·如何在 C 语言中管理 (2025-12-25 03:20:14)
·C语言和内存管理有什 (2025-12-25 03:20:11)
·为什么C语言从不被淘 (2025-12-25 03:20:08)