lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


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