2

I want to call an external lua_5.2 function from C, so I made a minimal example to try it out.

The minimal testfile:

--- filename: play.lua
function hello()
    print("Hello World!\n")
end

Trying to call this function from C:

#include <stdio.h>
#include <stdlib.h>

#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"


int
main(void) {
    lua_State *L;
    int status;
    int result;

    L = luaL_newstate();
    luaL_openlibs(L);

    status = luaL_loadfile(L, "play.lua");
    if (status != LUA_OK) {
        fprintf(stderr, "Could not load 'play.lua'!");
        exit(1);
    }

    lua_getglobal(L, "hello");
    if (lua_isfunction(L, -1)) {
        fprintf(stderr, "ERROR: Not a function!\n");
        exit(1);
    }

    result = lua_pcall(L, 0, 0, 0);
    if (result!= LUA_OK) {
        fprintf(sterr, "Error running lua: %i\n", result);
        exit(1);
    }
    fprintf(stdout, "lua ran fine\n");
    lua_pop(L, lua_gettop(L));

    lua_close(L);
    return 0;
}

Calling that executable results however in LUA_ERRUN (2)

Error running lua: 2

I am not quite sure what I am doing wrong here, and the documentation is a little bit opaque to me -- according to the 5.2 reference manual I am using pcall correctly (function with zero args and zero return vals), and I apparently grabbed the function from the stack correctly (otherwise they earlier error would have shown).

Any idea what I am doing wrong?

8
  • Try luaL_dofile instead of luaL_loadfile. which only loads but does not run a script. Commented Jul 3, 2023 at 15:05
  • 1
    The actual error message gets pushed to the stack doesn't it. It should give you more of an idea of what went wrong. Commented Jul 3, 2023 at 15:13
  • 1
    also shouldn't this be negated if (lua_isfunction(L, -1)) Commented Jul 3, 2023 at 15:21
  • 2
    I think they are probably right about the dofile, as in native lua I had to execute the function returned from load, before being able to execute the hello function. load(playLuaStr)(); hello();, so probably your lua_getglobal isn't working as hello doesn't exist. Commented Jul 3, 2023 at 16:10
  • 2
    A small problem: fprintf(sterr, "Error running lua: %i\n", result); - this example does not compile (sterr). Please ensure that you are copying your Minimal, Reproducible Example precisely - avoid transcribing by hand, when possible, and instead copy and paste complete examples immediately after checking their validity. It may seem minor, but typos like this can create doubt as to the correctness of other sections of the code! Commented Jul 3, 2023 at 17:02

1 Answer 1

2

When the return value of lua_pcall is not LUA_OK, an error message will have been pushed onto the top of the stack.

This value can be manipulated with functions like lua_tostring for use in C.

result = lua_pcall(L, 0, 0, 0);

if (result != LUA_OK) {
    fprintf(stderr, "Error running lua: %s\n", lua_tostring(L, -1));
    exit(1);
}

(You can also propagate the error with lua_error(L), but that may defeat the purpose of the protected call.)

Doing this reveals the error

Error running lua: attempt to call a nil value

which means lua_getglobal(L, "hello"); pushed nil onto the stack.

(Note that we only get this far because if (lua_isfunction(L, -1)) is the inverse condition to check for.)

The value of the global variable hello is nil because the chunk containing its definition was never executed. That is, luaL_loadfile (ultimately lua_load) only loads chunks, it does not execute them.

After loading a chunk, you may execute it like any other function (lua_call, etc.).

For example:

#include <stdio.h>
#include <stdlib.h>

#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"

int
main(void) {
    lua_State *L = luaL_newstate();

    luaL_openlibs(L);

    int status;
    int result;

    status = luaL_loadfile(L, "play.lua"); /* load the chunk */
    if (status != LUA_OK) {
        fprintf(stderr, "Could not load 'play.lua': %s\n", lua_tostring(L, -1));
        exit(1);
    }

    result = lua_pcall(L, 0, 0, 0); /* execute the chunk */
    if (result != LUA_OK) {
        fprintf(stderr, "Error running lua: %s\n", lua_tostring(L, -1));
        exit(1);
    }

    lua_getglobal(L, "hello");
    if (!lua_isfunction(L, -1)) {
        fprintf(stderr, "ERROR: Not a function!\n");
        exit(1);
    }

    result = lua_pcall(L, 0, 0, 0);
    if (result != LUA_OK) {
        fprintf(stderr, "Error running lua: %s\n", lua_tostring(L, -1));
        exit(1);
    }

    puts("lua ran fine");
    lua_close(L);
}

Output:

Hello World!

lua ran fine

Note that luaL_dofile is a macro defined as

(luaL_loadfile(L, filename) || lua_pcall(L, 0, LUA_MULTRET, 0))

and is a convenient way to load and execute a chunk.

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

Comments

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.