lua-users home
lua-l archive

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


It was thus said that the Great Björn Eiríksson once stated:
> Hello
> 
> I have made a test class in C code that exposes it self to Lua, it mostly
> works, the only problem is that I cannot get the setmetatable code to work
> from C++, so for testing purposes I have been setting that on the Lua side
> to verify that everything else works indeed.
> 
> Lua test code is as follows:
> 
> vec = CustomVector:new(1, 2, 3)  -- CustomVector is defined in C code
> 
> setmetatable(vec, { __index = CustomVector })  -- This one should be done
> in C code but I could not get it to work if I have it there.
> 
> io.write("<"..vec.x.." , "..vec.y.." , "..vec.z..">\n")
> 
> io.write(vec:Magnitude().."\n")
> 
> So my question is, does anyone have a example of how to do the
> setmetatable for case like this from C code ?

  What I do is the following (from some code I have):

static const struct luaL_Reg hashlua[] = 
{
  { "new"		, hashlua_new		} ,
	/* ... */
  { NULL		, NULL			}
};

static const struct luaL_Reg hashlua_meta[] =
{
  { "update"            , hashlua_update        } ,
  { "final"             , hashlua_final         } ,
  { "finalhexa"         , hashlua_finalhexa     } ,
  { "__tostring"        , hashlua___tostring    } ,
  { NULL                , NULL                  }
};

int luaopen_org_conman_hash(lua_State *const L)
{
  OpenSSL_add_all_digests();
   
  luaL_newmetatable(L,HASH_TYPE);
  luaL_register(L,NULL,hashlua_meta);
  lua_pushvalue(L,-1);
  lua_setfield(L,-2,"__index");
  
  luaL_register(L,"org.conman.hash",hashlua);
  /* rest of function */
}

This creates a metatable I can use with the "__index" field pointed to
itself.  In the code to create a new instance, I grab the metatable I
created:

static int hashlua_new(lua_State *const L)
{
  const EVP_MD *m;
  EVP_MD_CTX   *ctx;
  const char   *alg;

  alg = luaL_optstring(L,1,"md5");
  m   = EVP_get_digestbyname(alg);
  if (m == NULL)
  {
    lua_pushnil(L);
    return 1;
  }
  
  ctx = lua_newuserdata(L,sizeof(EVP_MD_CTX));
  EVP_DigestInit(ctx,m);
  luaL_getmetatable(L,HASH_TYPE);
  lua_setmetatable(L,-2);
  return 1;
}

  I use separate tables for main objects and metatables (I personally find
it cleaner that way) but there's no technical reason you can't use the same
table for both.

  -spc (I do hope this helps)