lualua 闭包函数传递到c/c++

我们搭建好了整个的项目环境,现在,我们一起探索一下如何将lua寄宿到C++中。
宿主的实现
我们在LuaWithCPPTest项目下,查看Source.cpp代码如下:
#include &iostream&
#include &fstream&
#include &string&
using namespace
extern &C&
#include &lua.h&
#include &lauxlib.h&
#include &lualib.h&
void TestLua();
int main()
TestLua();
void TestLua()
lua_State *L = luaL_newstate();
luaopen_base(L); //
luaopen_table(L); //
luaopen_package(L); //
luaopen_io(L); //
luaopen_string(L); //
luaL_openlibs(L); //打开以上所有的lib
while (true)
cout && &请输入Lua代码:& &&
getline(cin, str, '\n');
if (luaL_loadstring(L, str.c_str())
|| lua_pcall(L, 0, 0, 0) )
const char * error = lua_tostring(L, -1) ;
cout && string(error) &&
lua_close(L);
其中,被extern &C&包起来的是lua的主要函数的声明。在C++中,每个嵌入的lua的生命周期与各自的lua_State对象一一对应。通过luaL_newstate()方法,我们便创建了一个lua解释器。随后的几个luaopen_*方法,都是获取相应lua库的使用权,最后通过luaL_openlibs打开所有的有使用权的lua标准库。一切准备就绪后,我们开始接收输入。
我们通过luaL_loadstring,将所有代码读入lua,并且检查代码是否有语法错误。然后通过lua_pcall,运行代码,将所有的全局变量保存在_G中。通过读取、运行这两步,我们就建立起一个自己的lua解释器了。
将lua作为配置文件
从文件读取lua代码,流程与之前的示例一样,仅是将luaL_loadstring()换成luaL_loadfile()即可。代码如下: 
while (true)
cout && &输入lua文件路径:& &&
getline(cin, str, '\n');
if (luaL_loadfile(L, str.c_str())
|| lua_pcall(L, 0, 0, 0) )
const char * error = lua_tostring(L, -1) ;
cout && string(error) &&
现在,我们在lua中定义变量,并且赋值。然后在c++中取值,运算出结果。在lua文件中,内容如下:
在c++中,我们获取a,b两个变量的值,然后相加,算出结果:
#include &iostream&
#include &fstream&
#include &string&
using namespace
extern &C&
#include &lua.h&
#include &lauxlib.h&
#include &lualib.h&
void TestLua();
int main()
TestLua();
void TestLua()
lua_State *L = luaL_newstate();
luaopen_base(L); //
luaopen_table(L); //
luaopen_package(L); //
luaopen_io(L); //
luaopen_string(L); //
luaL_openlibs(L); //打开以上所有的lib
while (true)
cout && &输入lua文件路径:& &&
getline(cin, str, '\n');
if (luaL_loadfile(L, str.c_str())
|| lua_pcall(L, 0, 0, 0) )
const char * error = lua_tostring(L, -1) ;
cout && string(error) &&
int a = 0;
int b = 0;
// 获取a的值
lua_getglobal(L, &a&);
if (!lua_isnumber(L, -1))
cout && &-2 error& && lua_isnumber(L, -1) && lua_isnumber(L, -1) &&
a = lua_tonumber(L, -1);
// 获取b的值
lua_getglobal(L, &b&);
if (!lua_isnumber(L, -1))
cout && &-1 error& &&
b = lua_tonumber(L, -1);
cout && &a = & && a && & b = & && b &&
cout && &a + b = & && a + b &&
lua_close(L);
最后的得到结果如下:
将文件载入lua后,我们通过lua_getglobal()方法,将想要获得的lua值放入栈顶(栈为何物,下篇分析),然后用lua_isnumber(L, –1)来检测栈顶的元素是否是number,若果是,调用lua_tonumber(L,-1)来将栈顶的值传递给c++变量,整个流程为:1、将欲获得的lua值放入栈中;2、检测栈中的值是否ok;3、取出栈中的值。lua有一系列的lua_is*()来检测栈中的值是否是相应的*类型,相应的,也有一系列的lua_to*()来取值:
写这篇的时候,我内心比较纠结,在内容的深度上把握不准,最终我的定位是:这系列只描述两者之间交互的步骤、方式,不深入去描述原理。原因很简单,因为我的水平有限。在自己水平不足的情况下,去描述c++与lua内在的交互原理,会误导人。我目前的大纲是:第一篇搭建环境;第二篇描述C++调用lua的一些数据;第三篇讲解C++与lua之间的栈,主要还是偏重C++代码调用lua代码。第四篇描述lua如何调用c++代码。第五篇介绍工具tolua++。以上。
阅读(...) 评论()function createCountdownTimer(second)
local ms = second * 1000
local function countDown()
ms = ms - 1
return countDown
timer1 = createCountdownTimer(1)
for i = 1, 3 do
print(timer1())
一个函数所使用的定义在它的函数体之外的局部变量(external local variable)称为这个函数的upvalue。在前面的代码中,函数countDown使用的定义在函数createCountdownTimer中的局部变量ms就是countDown的upvalue,但ms对createCountdownTimer而言只是一个局部变量,不是upvalue。函数闭包
一个函数和它的所有upvalue构成了一个函数 闭包。函数闭包是Lua这一类&函数式&语言的核心概念。Lua函数闭包与C函数的比较Lua函数闭包使函数在几次调用间具有保持自身状态的能力,从此角度看,与带静态局部变量的C函数相似。但二者其实截然不同:前者是一个运行时对象,后者只是一个静态地址;前者可以有&同一类型&的若干实例,每个实例都有自己的状态(如前面的例子),而后者只是一个静态地址,谈不上实例化。
阅读(...) 评论()lua语言有如下两个特点:
1.lua中的函数可以被存放在变量、表中,也可以作为函数的参数,还可以作为函数的返回值,如:
      func = function()
        print("Hello");
      end
  等价于
      function func()
        print("Hello");
      end
  这两种写法都是函数func()的定义;并且下面这个例子:
      function func()
        return function()  print("Hello");  end  --函数作为返回值
      end
      local f1 = func();
      print(f1);            --运行结果:function:
      f1();              --运行结果:Hello
  是函数作为函数返回值的情况,其中f1是func()内部返回的函数,打印出来为函数在内存中的地址,f1()调用了内部函数,执行后打印出了"Hello"结果。
2.被嵌套的函数可以访问他外部函数中的变量(这个比较强悍,C语言只能访问全局的或以参数形式传入)。
  看如下例子:
    function func()
      local index = 0;        
      local inner = function()
        print(index);      
        index = index + 1;
      end
      inner();            --打印结果:0
      inner();            --打印结果:1
      print(index);           --打印结果:2
    end
    func();
  说明了func()中的局部变量index是可以在inner()中被使用和更改的,index被称为inner()的upvalue。
以上这两点是构成闭包的基础,也是lua语言的强大和灵活之处。
另外,将上面例子稍加改造,如下:
    function func()
      local index = 0;
      print("Hello");
      return function()
        print(index);
        index = index + 1;
      end
    end
    local&inner = func();    --调用func()函数,返回内部函数给inner,打印结果:"Hello"
    print(inner);        --打印结果:function:0037BE88
    inner();          --调用内部函数,打印结果:0
    inner();          --调用内部函数,打印结果:1
    local other = func();    --获取另一个内部函数实例,打印结果:"Hello"
    other();          --调用另一个内部函数实例,打印结果:0
    other();          --同上,打印结果:1
&由此可以看出函数的局部变量是可以保存在函数内部的,通过调用该函数内嵌的函数可以获取并修改局部变量的值,该函数的局部变量(upvalue)和内嵌函数的组合使用,形成了闭包,这看起来与C++中类的成员变量有些类似。函数具有闭包的功能后,不必再担心其局部变量没办法保存了,这一点对程序员的影响是很大的。
还有如下例子:
    function func();
      local index = 0;
      return function()
        index = index + 1;
        
      end
    end
    local inner = func();
    print(inner());      --打印结果:1
    print(inner());      --打印结果:2
调用了func()的内部函数实例,并将函数调用结果打印了出来,是个很好的保存局部变量的方式。
另外闭包常用于泛型for的迭代器中,由于太晚了,就不再赘述了。有问题欢迎讨论拍砖。
阅读(...) 评论()

我要回帖

更多关于 lua闭包 的文章

 

随机推荐