setmetatable from C code

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

setmetatable from C code

Björn Eiríksson
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 ?

Thanks

Björn




Reply | Threaded
Open this post in threaded view
|

Re: setmetatable from C code

Sean Conner
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)