Hi, list. I'm trying to understand how to write Lua modules from C (I use GSL as an example). Code is below.
#include <gsl/gsl_vector.h>
#include "lua.h"
#include "lauxlib.h"
#define VECTOR_MT "GSL vector"
static int vector_new(lua_State *L)
{
int i;
int n = lua_gettop(L);
gsl_vector *t = gsl_vector_alloc(n);
for (i = 0; i < n; i++)
{
gsl_vector_set(t, i, luaL_checknumber(L,i+1));
}
//Is this right?
gsl_vector *r = (gsl_vector *)lua_newuserdata(L, sizeof(gsl_vector));
*r = *t;
luaL_getmetatable(L, VECTOR_MT);
lua_setmetatable(L, -2);
return 1;
}
static int vector_get(lua_State *L)
{
gsl_vector *v = (gsl_vector *)lua_touserdata(L,1);
int max = (int)v->size;
int n = luaL_checkinteger(L,2)-1;
if ((0<=n) && (n <= max))
lua_pushnumber(L, gsl_vector_get(v,n));
else
lua_pushnil(L);
return 1;
}
static int vector_m_add(lua_State *L)
{
gsl_vector *v1 = (gsl_vector *)lua_touserdata(L,1);
gsl_vector *v2 = (gsl_vector *)lua_touserdata(L,2);
if ((v1 -> size) == (v2 -> size))
{
// I'm not sure whether this is right or not, but it seems to work so far
gsl_vector *t = gsl_vector_alloc(v1 -> size);
gsl_vector_memcpy(t, v1);
gsl_vector_add(t,v2);
gsl_vector *r = (gsl_vector *)lua_newuserdata(L, sizeof(gsl_vector));
luaL_getmetatable(L, VECTOR_MT);
lua_setmetatable(L, -2);
*r = *t;
}
else
{
lua_pushnil(L);
}
return 1;
}
static const struct luaL_Reg nicelib [] =
{
{"new", vector_new},
{"get", vector_get},
{NULL, NULL}
};
static const struct luaL_Reg nicelib_m [] =
{
{"__add", vector_m_add},
{NULL, NULL}
};
int luaopen_nice(lua_State *L)
{
luaL_newmetatable(L, VECTOR_MT);
lua_pushvalue(L, -1);
lua_setfield(L, -2, "__index");
luaL_setfuncs(L, nicelib_m, 0);
luaL_newlib(L, nicelib);
return 1;
}
I have two questions:
1. Am I right wrt "new", i.e., the way userdata is created?
2. According to some docs I've read, userdata content should be freed by defining a function for __gc. However, I don't understand when or how to do that, as defining a function using gsl_vector_free in the case above is giving me an error prompt complaining about an invalid pointer.
I don't want a ready-made application to create bindings to GSL or an already existing one (I think two are freely available in GitHub) as I only use it as an example. I don't want a Lua solution, either (I know how to do that using pure Lua). Instead, I want to better understand the way Lua modules are defined when C is used, and perhaps to better understand C given that pointers are not intuitive for me. Thank you in advance and sorry for any inconvenience caused by this noob question.
Best regards,
Jairo