2

I'm looking for a way to be able to read lua's main function in my c code.

I'm also looking for a way to pass a C function to lua

In my sample code LoadTBL would be the function that comes from the C code

TBL = 
{
    { Init,     0, 15, 00 },
    { End,      1, 16, 00 }
}

function main()

    for key, value in pairs(TBL) do
        result, msg = LoadTBL(value[1], value[2], value[3]);
        if( not result ) then return false, msg;
        end
    end
        
    return true, "success";
end

C code:

int LoadTBL (int val1, int val2, int val3) {
    ....
    return 0;
}


void read_test(void) {
    lua_State *L;
    L = luaL_newstate();
    luaL_openlibs(L);

    if (luaL_loadfile(L, "test.lua") || lua_pcall(L, 0, 0, 0))
    {
        printf("Error 'test.lua'\n");
        return;
    }

    lua_close(L);
    printf("Read complete.\n");

}

The idea is to create luas scripts that can interact with C codes

  • Please note I've posted an answer below that assumes *"read lua's main function in my c code"* means to load/run the containing file, similar to your example C code, and then be able to execute the `main` function. Otherwise, see this [question](https://stackoverflow.com/q/14720930/2505965) for dumping a function to a string. – Oka Nov 24 '22 at 06:58

1 Answers1

1

You will want to spend more time reading about the Lua C API.

Here is an example of a C program, or host, that creates a Lua state, registers a global function, and executes a Lua file. Once the file is finished executing, the host program gets the global Lua value main, and attempts to call it. If successful, the host reads the return values from the stack, and prints them.

Note how the C function is defined as a lua_CFunction, and interacts with the Lua stack.

I'm not sure what you expect this LoadTBL function to do, so for demonstration purposes, the one below checks that all its arguments are integers and are evenly divisible.

main.c:

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

void die(lua_State *L, const char *msg)
{
    fprintf(stderr, "%s: %s\n", msg, lua_tostring(L, -1));
    lua_close(L);
    exit(EXIT_FAILURE);
}

int loadTBL(lua_State *L)
{
    int n = lua_gettop(L);
    int even = 1;

    for (int i = 1; i <= n; i++) {
        if (!lua_isinteger(L, i) || (lua_tointeger(L, i) % 2 != 0)) {
            even = 0;
            break;
        }
    }

    lua_pushboolean(L, even);
    lua_pushstring(L, "some message");
    return 2;
}

int main(void)
{
    lua_State *L = luaL_newstate();
    luaL_openlibs(L);
    lua_register(L, "LoadTBL", loadTBL);

    if (LUA_OK != luaL_dofile(L, "test.lua"))
        die(L, "dofile");

    lua_getglobal(L, "main");

    if (LUA_OK != lua_pcall(L, 0, 2, 0))
        die(L, "calling main");

    printf("GOT <%d>[%s]\n", lua_toboolean(L, -2), lua_tostring(L, -1));
    lua_close(L);
}

test.lua:

local TBL = {
    { 0, 15, 0 },
    { 1, 16, 0 }
}

function main()
    for key, value in pairs(TBL) do
        local result, msg = LoadTBL(value[1], value[2], value[3])

        if not result then
            return false, msg
        end
    end

    return true, "success"
end
Oka
  • 23,367
  • 6
  • 42
  • 53
  • Interesting how you did it, I was trying to use `luaL_Reg`, I liked the way you used it – alberto silva Nov 24 '22 at 16:57
  • [`luaL_Reg`](https://www.lua.org/manual/5.4/manual.html#luaL_Reg) is also a perfectly valid way to expose C functions to Lua, though it is usually used when creating a *library* (shared object) - something your Lua programs can [`require`](https://www.lua.org/manual/5.4/manual.html#pdf-require). See [`luaL_newlib`](https://www.lua.org/manual/5.4/manual.html#luaL_newlib) / [`luaL_setfuncs`](https://www.lua.org/manual/5.4/manual.html#luaL_setfuncs). – Oka Nov 24 '22 at 17:02