VC++和Lua交互(VC调用Lua函数)

来源:互联网 发布:网络流行语盘点 编辑:程序博客网 时间:2024/06/05 13:59

VC++ 与 lua 交互(二) ---- VC 调用 lua函数

--LuaTest.lua

Function MaxMin(x,y)

    If x > y then

        return "x > y", x, y

    elseif x == y then

        return "x == y",x, y

    else 

        return"y > x ", y ,x

    end

end

 

//测试程序

// LuaTest.cpp : 定义控制台应用程序的入口点。

#include"stdafx.h"

//包含头文件,这个头文件里包含了其他3个文件

//为了引用方便,我们可以直接将lua的文件拷贝到vs的include/lua52目录下

#include<Lua52/lua.hpp>

#include<iostream>

usingnamespacestd;

 

//将编译好的lua文件导入,这样将不依靠lua的dll来执行代码。Lib文件是根据lua5.2直接编译而来,如果不导入lib的引用,下面lua的函数讲无法识别

//为了方便起见,我们可以直接将lib文件拷贝到vs目录下的lib文件夹下

#pragmacomment(lib"Lua52.lib")

 

voidMaxMin(lua_StateLintxinty)

{

     //获取函数名称

    lua_getglobal(L"MaxMin");

     //压入参数,x

    lua_pushnumber(Lx);

     //压入参数,y

    lua_pushnumber(Ly);

     //调用开始,指定参数个数,返回值个数,最后一个值指定错误处理过程,为空的时候,没有错误处理过程

    lua_pcall(L, 2, 3,0);

     //返回值依次压栈,第一个返回值最先被压栈,如果有n个返回值,那么第一个返回值的位置为-n,最后一个返回值为-1

    const  charclua_tostring(L, -3);

    //取出第二个返回值

    lua_Numbernum1lua_tonumber(L, -2);

     //取出第一个返回值

    lua_Numbernum2lua_tonumber(L, -1);

    //输出结果

    cout<< c<< ","<< "Max = "<< num1<<","<< "Min= "<< num2<< endl;

    //元素出栈,将个返回值的堆栈清掉

    lua_pop(L, 3);

}

 

int_tmain(intargc_TCHARargv[])

{

    //新建一个lua执行虚拟机

    lua_State*LluaL_newstate();

     //加载lua文件,如果加载成功的话,就执行其中的调用。加载的过程其实是一个获取并编译的过程

     //lua文件的路径为当前路径,在IDE环境下,即是工程文件目录。

     //在这里特别要注意,当luaL_loadfile函数执行成功的时候返回值为0,lua_pcall也一样

    if(luaL_loadfile(L,"LuaTest.lua")== 0)

    {   

        //初始化函数调用,如果没有这一句,将无法获取到函数的实体

        if(lua_pcall(L, 0, 0, 0) == 0)

        {

             //调用lua函数执行

            MaxMin(L, 2, 3);

            MaxMin(L, 4, 4);

            MaxMin(L, 5, 2);

        }

    }

     //关闭lua虚拟机

    lua_close(L);

    return0;

}

编译的过程中会存在库包含冲突的问题:

1>LINK : warning LNK4098: 默认库“MSVCRT”与其他库的使用冲突;请使用 /NODEFAULTLIB:library

1>MSVCRT.lib(cinitexe.obj) : warning LNK4098: 默认库“libcmt.lib”与其他库的使用冲突;请使用 /NODEFAULTLIB:library


这个时候只需要去掉其中一个连接lib就okay了。

在连接选项里加上

/NODEFAULTLIB:MSVCRTD.lib  或者 /NODEFAULTLIB:libcmt.lib。


当然了如果使用MSVCRTD.lib将会使可执行文件小很多。



执行结果:

 

   问题1:lua_pcall(L, 0, 0, 0),执行这一句的意义?

  一开始我一直认为既然luaL_loadfile执行以后,就可以直接调用lua_getglobal获得LuaTest.lua中的函数,其实不然。手册中明确提到,lua_load把一个lua文件当作一个chunk编译后放到stack的栈顶,而什么是chunk呢?chunk就是一个可执行语句的组合,可以是一个文件也可以是一个string

“Lua handles a chunk as the body of an anonymous function with a variable number of arguments” 这是Lua对chunk也就是lua文件的处理方式,就是认为是一个可变参数的匿名函数。也就是说,调用后栈上有一个匿名函数,这个函数的body就是文件中所有的内容。

在luaL_loadfile后,调用lua_getop以及lua_type可以知道栈的大小为1,放在栈上的是一个fucntion类型的value。为什么loadfile后我们不能直接获取到printmsg这个函数呢,那是因为刚才提到的,loadfile仅仅是编译lua文件,并不执行这个文件,也就是说只是在栈上形成了一个匿名函数。只有执行这个函数一次,才会使得MaxMin可以通过lua_getglobal获取否则,全局变量是空的。我在手册上看到这样一句话:Lua在执行函数的时候,函数会实例化,获得的closure也是这个函数的最终值。其实不管视函数,还是其他类型,如果不执行的话,它们只是被编译,并不能在进程的空间种获取到他们,感觉就像c的库一样,他们的编译文件.so已经存在,但是如果你不调用它,那么库中所有的变量不能被实例化,调用者也就无法访问。


   问题2.我们注意到,我们执行lua函数的时候使用的是lua_pcall(),在lua里还有另外一个函数lua_call,这个两个函数有啥区别?

    lua_call的运行是无保护的,他与lua_pcall相似,但是在错误发生的时候她抛出错误而不是返回错误代码。当你在应用程序中写主流程的代码时,不应该使用lua_call,因为你应该捕捉任何可能发生的错误。当你写一个函数的代码时,使用lua_call是比较好的想法,如果有错误发生,把错误留给关心她的人去处理.

同样的还有

   luaL_newstate用c运行库的内存分配函数

   lua_newstate可自定义内存分配函数。

原创粉丝点击