|
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: