1

I'm trying to learn Lua and how to interface to and from C with it. My first attempt follows but has been simplified to include only the issue I'm seeing.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <linux/limits.h> /* For PATH_MAX */
#include <unistd.h>
#include <getopt.h>
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>

#define EXITF exit(EXIT_FAILURE)

lua_State* lua;

void stackDump(lua_State* lua)
{
    int i, t;
    int top = lua_gettop(lua);

    for (i = 1; i <= top; i++)
    {
        t = lua_type(lua, i);

        switch (t)
        {
            case LUA_TSTRING:
                printf("\"%s\"", lua_tostring(lua, i));
                break;

            case LUA_TBOOLEAN:
                printf(lua_toboolean(lua, i) ? "true" : "false");

            case LUA_TNUMBER:
                printf("%g", lua_tonumber(lua, i));
                break;

            default:
                printf("%s", lua_typename(lua, t));
                break;
        }

        if (i < top)
           printf(", ");
    }

    printf("\n");
}

int main(int argc, char** argv)
{
    int opt;
    char cfgFile[PATH_MAX];
    cfgFile[0] = 0;

    lua = luaL_newstate();
    luaL_openlibs(lua);

    stackDump(lua);

    while ((opt = getopt(argc, argv, "c:")) != -1)
    {
        switch (opt)
        {
            case 'c':
                strncpy(cfgFile, optarg, PATH_MAX);
                cfgFile[PATH_MAX - 1] = 0;
                break;
        }
    }

    if (cfgFile[0] == 0)
    {
        fprintf(stderr, "No cfg file specified\n");
        return EXIT_FAILURE;
    }

    printf("cfgFile = \"%s\"\n", cfgFile);

    if (luaL_loadfile(lua, cfgFile) != LUA_OK)
    {
        fprintf(stderr, "%s\n", lua_tostring(lua, -1));
        lua_pop(lua, 1);
        lua_close(lua);
        return EXIT_FAILURE;
    }

    stackDump(lua);

    lua_getglobal(lua, "program");

    stackDump(lua);

    if (lua_isstring(lua, -1) == 0)
    {
        fprintf(stderr, "`program` should be a string\n");
        lua_close(lua);
        return EXIT_FAILURE;
    }

    char execArg0[256];

    strncpy(execArg0, lua_tostring(lua, -1), 256);
    lua_pop(lua, 1);

    lua_close(lua);

    return EXIT_SUCCESS;
}

Lua script:

#!/usr/bin/env lua

program = "echo"

What I'm seeing when running this is:

$ ./wrapper2 -c wrapper2.lua

cfgFile = "wrapper2.lua"
function
function, nil
`program` should be a string

Note that the empty line is intentional; stackDump() tells us that the stack is empty at that point. It seems that the call to lua_getglobal(lua, "program") is pushing nil on the stack instead of the string "echo". Please could you help me work out why I'm seeing this?

As a side question: why is there a function pushed on the stack (presumably by luaL_loadfile())? I don't remember reading that functions are pushed on the stack automatically.

2
  • 1
    Could you consider editing it to MCVE? Commented Sep 30, 2015 at 18:57
  • @cubuspl42 Apologies, I'm modifying the question to include only the issue at hand. Commented Sep 30, 2015 at 19:03

1 Answer 1

3

luaL_loadfile loads a Lua script but does not execute it and so does not define the global program. Use luaL_dofile instead.

luaL_loadfile compiles a Lua script and leaves the code as a Lua function on the stack.

luaL_dofile calls luaL_loadfile and then calls that function.

See the manual entries for luaL_loadfile and luaL_dofile.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for your answer. Can you help me with why there's a function on the stack after the luaL_loadfile()?
@Doddy: Because that's how it's defined to work. luaL_loadfile is equivalent to luaL_loadfilex with mode equal to NULL. luaL_loadfilex returns the same results as lua_load. lua_load "pushes the compiled chunk as a Lua function on top of the stack" (or pushes an error message). Start at lua.org/manual/5.3/manual.html#luaL_loadfile and follow the links.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.