Lua笔记(7)——luaL_loadfile和luaL_dofile的区别

luaL_loadfile()会加载和编译Lua脚本,但不会运行。而luaL_dofile不仅运行编译后的脚本,运行结束后还会把脚本pop出栈。看下面这个例子:

一个简单的脚本(test.lua):

print "Hello World!"

首先看调用luaL_loadfile()的程序:

#include <stdio.h>
#include <stdlib.h>
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"

static void stackDump(lua_State *L)
{
    int i = 0;
    int type = 0;
    int top = lua_gettop(L);

    printf("There is %d elements in stack: ", top);
    for (i = 1; i <= top; i++)
    {
        type = lua_type(L, i);
        switch (type)
        {
            case LUA_TSTRING:
            {
                printf("'%s'", lua_tostring(L, i));
                break;
            }
            case LUA_TBOOLEAN:
            {
                printf(lua_toboolean(L, i) ? "true" : "false");
                break;
            }
            case LUA_TNUMBER:
            {
                printf("%g", lua_tonumber(L, i));
                break;
            }
            default:
            {
                printf("Element type is %s", lua_typename(L, type));
                break;
            }
        }
        printf(" ");
    }
    printf("\n");
    return;
}

static void bail(lua_State *L)
{
    fprintf(stderr, "\nFATAL ERROR:%s\n\n", lua_tostring(L, -1));
    exit(1);
}
int main(void)
{   
    lua_State *L = luaL_newstate();

    luaL_openlibs(L);

    if (luaL_loadfile(L, "test.lua"))
    {
        bail(L);
    }

    stackDump(L);

    lua_close(L);
    return 0;
}

执行结果:

[root@Fedora test]# ./a
There is 1 elements in stack: Element type is function

可以看到,并没有打印“Hello World!”,而且栈里还有一个类型为function的元素。

接下来看调用luaL_dofile()的程序:

#include <stdio.h>
#include <stdlib.h>
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"

static void stackDump(lua_State *L)
{
    int i = 0;
    int type = 0;
    int top = lua_gettop(L);

    printf("There is %d elements in stack: ", top);
    for (i = 1; i <= top; i++)
    {
        type = lua_type(L, i);
        switch (type)
        {
            case LUA_TSTRING:
            {
                printf("'%s'", lua_tostring(L, i));
                break;
            }
            case LUA_TBOOLEAN:
            {
                printf(lua_toboolean(L, i) ? "true" : "false");
                break;
            }
            case LUA_TNUMBER:
            {
                printf("%g", lua_tonumber(L, i));
                break;
            }
            default:
            {
                printf("Element type is %s", lua_typename(L, type));
                break;
            }
        }
        printf(" ");
    }
    printf("\n");
    return;
}

static void bail(lua_State *L)
{
        fprintf(stderr, "\nFATAL ERROR:%s\n\n", lua_tostring(L, -1));
        exit(1);
}
int main(void)
{
    lua_State *L = luaL_newstate();

    luaL_openlibs(L);

    if (luaL_dofile(L, "test.lua"))
    {
        bail(L);
    }

    stackDump(L);

    lua_close(L);
    return 0;
}

执行结果:

[root@Fedora test]# ./a
Hello World!
There is 0 elements in stack:

可以看到,不仅打印了“Hello World!”,而且栈也变成了空。

参考资料:
lual_dofile(); wont load script with C++ and Lua

Lua笔记(6)——栈(stack)

C程序和Lua库之间通过栈(stack)来进行数据交换,并且栈中的每个槽位(slot)都能存放任意的Lua数据类型值。栈如下图所示:

                            |________|    <--  (-1)
                            |________|    <--  (-2)
                            |________|
                            | ...... |
                            |________|    <--  (2)
                            |________|    <--  (1)

栈底以1为起始索引,而栈顶则以-1作为起始索引。lua_gettop()函数可以返回当前栈中的元素个数,同时也是栈顶元素的索引值。如果是空栈,则 lua_gettop()返回0

Lua C API的核心就集中在对栈的操作上:当想要运行某个Lua脚本时,需要调用luaL_dofile()函数。而想执行Lua脚本的某个函数时,则首先要把函数push进栈(lua_getglobal()),如果函数需要参数,则参数也要相应地进栈(lua_pushXX())。接下来执行函数(比如lua_pcall()函数)。当函数退出时,返回值同样push进栈,C程序就可以使用lua_toXX()函数获得结果。请看下面这个例子:

一个简单的Lua脚本(test.Lua):

function add (a, b)
    return (a+b)
end

C程序如下:

#include <stdio.h>
#include <stdlib.h>
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"

static void bail(lua_State *L)
{
    fprintf(stderr, "\nFATAL ERROR:%s\n\n", lua_tostring(L, -1));
    exit(1);
}
int main(void)
{   
    lua_State *L = luaL_newstate();

    luaL_openlibs(L);

    if (luaL_dofile(L, "test.lua"))
    {
        bail(L);
    }

    lua_getglobal(L, "add");


    lua_pushnumber(L, 1);
    lua_pushnumber(L, 2);

    if (lua_pcall(L, 2, 1, 0))
    {
        bail(L);
    }

    printf("%g\n", lua_tonumber(L, -1));

    lua_close(L);
    return 0;
}

执行结果如下:

3