Warning: this is an htmlized version!
The original is here, and
the conversion rules are here.
-- This file:
--   http://anggtwu.net/LUA/CLua1.lua.html
--   http://anggtwu.net/LUA/CLua1.lua
--          (find-angg "LUA/CLua1.lua")
-- Author: Eduardo Ochs <eduardoochs@gmail.com>
--
-- Introduction
-- ============
-- This file implements several ways to define Lua functions in C
-- using templates. For example, suppose that we want to define a
-- function "add" whose body is:
--
--   lua_pushnumber(L, lua_tonumber(L, 1) - lua_tonumber(L, 2));
--   return 1;
--
-- One way to do that is to run this,
--
--    buildandload('add', [=[
--      lua_pushnumber(L, lua_tonumber(L, 1) - lua_tonumber(L, 2));
--      return 1;
--    ]=])
--
-- that creates a file /tmp/clua_001.c with these contents,
--
--   #include "lauxlib.h"
--   #include <stdio.h>
--   static int my_add(lua_State* L) {
--     lua_pushnumber(L, lua_tonumber(L, 1) - lua_tonumber(L, 2));
--     return 1;
--   }
--   static const struct luaL_reg clua_001_lib[] = {
--     {"add", my_add},
--     {NULL, NULL}
--   };
--   LUALIB_API int luaopen_clua_001(lua_State *L) {
--     lua_pushvalue(L, LUA_GLOBALSINDEX);
--     luaL_openlib(L, NULL, clua_001_lib, 0);
--     return 0;
--   }
--
-- and then it compiles it with gcc or clang, and then loads the
-- resulting .so with either "require" or "package.loadlib".
--
--
-- Testing
-- =======
-- There are complete instructions here:
--
--   (find-lua-tutorial-intro "4. CLua1.lua")
--   (find-lua-tutorial-intro "5. CLua1.lua from the outside")
--   http://anggtwu.net/eev-intros/find-lua-tutorial-intro.html#4
--   http://anggtwu.net/eev-intros/find-lua-tutorial-intro.html#5
--
-- Etc
-- ===
-- See: (find-angg ".emacs.templates" "find-luaso-links")
--      (find-es "lua5" "CLua1.lua")

-- Index:
-- «.templates»			(to "templates")
-- «.CLua»			(to "CLua")
-- «.CLua-tests»		(to "CLua-tests")
-- «.buildandload»		(to "buildandload")
-- «.buildandload-tests»	(to "buildandload-tests")

require "Dang1"   -- (find-angg "LUA/Dang1.lua")


--  _                       _       _            
-- | |_ ___ _ __ ___  _ __ | | __ _| |_ ___  ___ 
-- | __/ _ \ '_ ` _ \| '_ \| |/ _` | __/ _ \/ __|
-- | ||  __/ | | | | | |_) | | (_| | ||  __/\__ \
--  \__\___|_| |_| |_| .__/|_|\__,_|\__\___||___/
--                   |_|                         
--
-- «templates»  (to ".templates")
--
CLua_C = Dang.from [=[
#include "lauxlib.h"
#include <stdio.h>
static int my_<<.funname>>(lua_State* L) {
<<.funbody>>
}
static const struct luaL_reg <<.modname>>_lib[] = {
  {"<<.funname>>", my_<<.funname>>},
  {NULL, NULL}
};
LUALIB_API int luaopen_<<.modname>>(lua_State *L) {
  lua_pushvalue(L, LUA_GLOBALSINDEX);
  luaL_openlib(L, NULL, <<.modname>>_lib, 0);
  return 0;
}
]=]
CLua_sh_debian = Dang.from [=[
  CFLAGS="-g -Wall -shared"
  LUADIR=/usr/include/lua5.1
  echo gcc $CFLAGS -I$LUADIR -o <<.fnamenoext>>.so <<.fnamenoext>>.c
       gcc $CFLAGS -I$LUADIR -o <<.fnamenoext>>.so <<.fnamenoext>>.c && echo OK
  ls -lAF <<.fnamenoext>>*
]=]
CLua_sh_mac = Dang.from [=[
  CFLAGS="-g -Wall -shared -undefined dynamic_lookup"
  LUADIR=/opt/local/include/lua5.1
  echo gcc $CFLAGS -I$LUADIR -o <<.fnamenoext>>.so <<.fnamenoext>>.c
       gcc $CFLAGS -I$LUADIR -o <<.fnamenoext>>.so <<.fnamenoext>>.c && echo OK
  ls -lAF <<.fnamenoext>>*
]=]
CLua_lua_require = Dang.from [=[
  Path.prependtocpath "<<.dir>>?.so"
  require "<<.fnamebase>>"
]=]
CLua_lua_loadlib = Dang.from [=[
  package.loadlib("<<.fnamenoext>>.so", "luaopen_<<.modname>>")()
]=]


--   ____ _                
--  / ___| |   _   _  __ _ 
-- | |   | |  | | | |/ _` |
-- | |___| |__| |_| | (_| |
--  \____|_____\__,_|\__,_|
--                         
-- «CLua»  (to ".CLua")

CLua = Class {
  type  = "CLua",
  n     = 0,
  from3 = function (fnameC, funname, funbody)
      local fnamenoext = fnamesansextension(fnameC)
      local fnamebase  = fnamebase(fnameC)
      local dir        = fnamedirectory(fnameC)
      local modname    = fnamebase
      return CLua {fnameC=fnameC,
                   fnamenoext=fnamenoext,
                   fnamebase=fnamebase,
                   dir=dir,
                   modname=modname,
                   funname=funname,
                   funbody=funbody}
    end,
  from2 = function (funname, funbody)
      CLua.n = CLua.n + 1
      local fnameC = format("/tmp/clua_%03d.c", CLua.n)
      return CLua.from3(fnameC, funname, funbody)
    end,
  rm = function (clb) print(getoutput("rm -fv /tmp/clua*")) end,
  --
  __tostring = function (clb)
      local f = function (k) return format("  %-11s %s", k..":", clb[k]) end
      return mapconcat(f, sortedkeys(clb), "\n")
    end,
  __index = {
    _C       = function (clb) return CLua_C          (clb) end,
    _debian  = function (clb) return CLua_sh_debian  (clb) end,
    _mac     = function (clb) return CLua_sh_mac     (clb) end,
    _require = function (clb) return CLua_lua_require(clb) end,
    _loadlib = function (clb) return CLua_lua_loadlib(clb) end,
    --
    C        = function (clb) ee_writefile(clb.fnameC, clb:_C()); return clb end,
    debian   = function (clb) print(getoutput(clb:_debian())); return clb end,
    mac      = function (clb) print(getoutput(clb:_mac())); return clb end,
    require  = function (clb) eval(clb:_require()); return clb end,
    loadlib  = function (clb) eval(clb:_loadlib()); return clb end,
  },
}


-- «CLua-tests»  (to ".CLua-tests")
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "CLua1.lua"

-- Choose one:
CLua.__index.compile = CLua.__index.mac
CLua.__index.compile = CLua.__index.debian

clb = CLua.from3("/tmp/clua_042.c", "foo", "return 0;") 
PPV(clb)
= clb
= clb:_C()
= clb:_debian()
= clb:_mac()
= clb:_require()
= clb:_loadlib()

= clb:C()
  clb:compile()
  clb:require()
= foo()

CLua.rm()
CLua.n = 0

clb = CLua.from2("foo", "lua_pushnumber(L, 33);  return 1;") 
= clb:C():compile():loadlib()
= foo()

clb = CLua.from2("foo", "lua_pushnumber(L, 333); return 1;") 
= clb:C():compile():loadlib()
= foo()

--]==]


--  _           _ _     _                 _ _                 _ 
-- | |__  _   _(_) | __| | __ _ _ __   __| | | ___   __ _  __| |
-- | '_ \| | | | | |/ _` |/ _` | '_ \ / _` | |/ _ \ / _` |/ _` |
-- | |_) | |_| | | | (_| | (_| | | | | (_| | | (_) | (_| | (_| |
-- |_.__/ \__,_|_|_|\__,_|\__,_|_| |_|\__,_|_|\___/ \__,_|\__,_|
--                                                              
-- «buildandload»  (to ".buildandload")
buildandload = function (funname, funbody)
    clb = CLua.from2(funname, funbody)
    clb:C():compile():loadlib()
    return clb
  end

-- «buildandload-tests»  (to ".buildandload-tests")
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "CLua1.lua"

-- Choose one:
CLua.__index.compile = CLua.__index.mac
CLua.__index.compile = CLua.__index.debian

CLua.rm()
buildandload("foo", [=[ lua_pushstring(L,"orig");      return 1; ]=])
= foo()  
buildandload("foo", [=[ lua_pushstring(L,"redefined"); return 1; ]=])
= foo()

= clb
= clb:_C()
= clb:_debian()
= clb:_loadlib()
= clb:_require()

--]==]









-- Local Variables:
-- coding:  utf-8-unix
-- End: