Extending Lua: Writing C Modules
Upvalues for C functions: lua_pushcclosure(L, f, n) and lua_upvalueindex(i) give C functions private state.
Errors: luaL_error(L, "bad value: %d", x) raises a Lua error (via longjmp, or C++ exceptions if Lua is compiled as C++). Don't leak C resources across errors.
// mylib.c → gcc -O2 -shared -fPIC -I/usr/include/lua5.4 mylib.c -o mylib.so
#include <lua.h>
#include <lauxlib.h>
#include <math.h>
// A C function receives arguments on the stack and returns the number of results
static int l_add(lua_State *L) {
lua_Number a = luaL_checknumber(L, 1);
lua_Number b = luaL_checknumber(L, 2);
lua_pushnumber(L, a + b);
return 1;
}
static int l_stats(lua_State *L) {
luaL_checktype(L, 1, LUA_TTABLE);
lua_Integer n = luaL_len(L, 1);
double sum = 0, sumsq = 0;
for (lua_Integer i = 1; i <= n; i++) {
lua_geti(L, 1, i);
double v = luaL_checknumber(L, -1);
lua_pop(L, 1);
sum += v; sumsq += v * v;
}
double mean = n ? sum / n : 0;
lua_pushnumber(L, mean);
lua_pushnumber(L, n ? sqrt(sumsq / n - mean * mean) : 0);
return 2; // two results: mean, stddev
}
static int l_greet(lua_State *L) {
const char *name = luaL_optstring(L, 1, "world");
lua_pushfstring(L, "Hello, %s!", name);
return 1;
}
static const luaL_Reg mylib_funcs[] = {
{"add", l_add},
{"stats", l_stats},
{"greet", l_greet},
{NULL, NULL}
};
int luaopen_my
…local mylib = require("mylib") -- finds mylib.so via package.cpath
print(mylib.add(2, 3), mylib.stats({1, 2, 3, 4}), mylib.greet("Lua"), mylib.version)