Comment

Comment by gucci-on-fleek

> you may have to compile each binary module

Correct, but I'd argue that you need to do this anyways (well, I do this anyways), because I don't like the alternative of redistributing binaries compiled by random third parties from the internet.

> link everything against the Lua VM, and write glue/loading code to make everything work together (see the comment below regarding LuaSocket)

> Of course, it's possible. But it's a lot of manual work, especially for newcomers.

To be clear, I think that your project is great, but this really isn't that much work:

  # FILE: .gitignore
  program
  *.luac
  *.o
  
  # FILE: Makefile
  CFLAGS := -std=c23 -Wall -Wextra -Werror
  
  ifeq "${mode}" "debug"
      CFLAGS += -ggdb3 -fanalyzer -fsanitize=address,undefined,leak
  else
      CFLAGS += -O2 -flto -s
  endif
  
  %.luac: %.lua
      luac -o $@ $^
  
  %.o: %.c
      ${CC} -c -o $@ $< ${CFLAGS}
  
  c_libraries := library.o
  lua_libraries := main.luac
  
  program: main.c ${c_libraries} ${lua_libraries}
      ${CC} -o $@ $< ${c_libraries} ${CFLAGS} -llua
  
  // FILE: library.c
  #include <lauxlib.h>
  #include <lua.h>
  #include <lualib.h>
  #include <stdcountof.h>
  
  static int test(lua_State *L) {
      lua_pushstring(L, "Hello from C!");
      return 1;
  }
  
  int luaopen_library(lua_State *L) {
      luaL_Reg library[] = {
          {"test", test},
          {nullptr, nullptr},
      };
      luaL_newlib(L, library);
      return 1;
  }
  
  // FILE: main.c
  #include <lauxlib.h>
  #include <lua.h>
  #include <lualib.h>
  #include <stdcountof.h>
  
  #define preload_c_lib(name)                       \
      do {                                          \
          extern int luaopen_##name(lua_State * L); \
          lua_pushcfunction(L, luaopen_##name);     \
          lua_setfield(L, -2, #name);               \
      } while (0)
  
  #define preload_lua_lib(name)                                         \
      do {                                                              \
          luaL_loadbufferx(L, &name[0], countof(name) - 1, #name, "b"); \
          lua_setfield(L, -2, #name);                                   \
      } while (0)
  
  static void initialize_modules(lua_State *L) {
      // Load standard modules.
      luaL_openlibs(L);
  
      // Load external modules.
      lua_getglobal(L, "package");
      lua_getfield(L, -1, "preload");
  
      // "main.lua"
      static char const main[] = {
          #embed "main.luac" suffix(, '\0')
      };
      preload_lua_lib(main);
  
      // "library.o"
      preload_c_lib(library);
  
      lua_settop(L, 0);
  }
  
  int main() {
      lua_State *L = luaL_newstate();
  
      // Initialize the modules.
      initialize_modules(L);
  
      // Run main script
      if (luaL_dostring(L, "require('main')()") != LUA_OK) {
          printf("Error: %s", lua_tostring(L, -1));
      }
  
      lua_close(L);
      return 0;
  }
  
  -- FILE: main.lua
  return function()
      local library = require("library")
      print(library.test())
      print("Hello from Lua!")
  end
To run:

  $ make && ./program
  cc -o program main.c library.o -std=c23 -Wall -Wextra -Werror -O2 -flto -s -llua
  Hello from C!
  Hello from Lua!

No comments yet

Be the first to share your thoughts.

Live from the official Hacker News API

A modern reader for Hacker News · SvelteKit + Skeleton