lua-users home
lua-l archive

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


Since you in C/C++ take a look at how LUNA is doing things.  I'm no
vertran myself, but I have had some problems with methods in Delphi
(actually enough that I believe I see your problem).

You need to track your methods table, object meta table, and object
table.  For example some working code of mine (note again Delphi not C)
is:

procedure RegisterMyClass(LuaScript:TLUAWrapper);
var
  MetaTable,
  MethodTable,
  Methods : Integer;
begin
  lua_newtable(LuaScript.LuaState);
  Methods := lua_gettop(LuaScript.LuaState);

// Lua<#ClassName#>ClassName - represents the class name in text
  luaL_newmetatable(LuaScript.LuaState, Lua<#ClassName#>ClassName); 
  MetaTable := lua_gettop(LuaScript.LuaState);
  
  lua_pushstring(LuaScript.LuaState, Lua<#ClassName#>ClassName); 
  lua_pushvalue(LuaScript.LuaState, Methods);
  lua_settable(LuaScript.LuaState, LUA_GLOBALSINDEX);

  lua_pushliteral(LuaScript.LuaState, '__metatable');
  lua_pushvalue(LuaScript.LuaState, Methods);
  lua_settable(LuaScript.LuaState, MetaTable);

  lua_pushliteral(LuaScript.LuaState, '__index');
  lua_pushcfunction(LuaScript.LuaState, index_<#ClassName#>);
  lua_settable(LuaScript.LuaState, MetaTable);

  lua_pushliteral(LuaScript.LuaState, '__newindex');
  lua_pushcfunction(LuaScript.LuaState, newindex_<#ClassName#>);
  lua_settable(LuaScript.LuaState, MetaTable);

  lua_pushliteral(LuaScript.LuaState, '__gc');
  lua_pushcfunction(LuaScript.LuaState, gc_<#ClassName#>);
  lua_settable(LuaScript.LuaState, MetaTable);

  lua_newtable(LuaScript.LuaState);
  MethodTable := lua_gettop(LuaScript.LuaState);
  lua_pushliteral(LuaScript.LuaState, '__call');
  lua_pushcfunction(LuaScript.LuaState, new_<#ClassName#>);
  lua_pushliteral(LuaScript.LuaState, '__new');
  lua_pushvalue(LuaScript.LuaState, -2);
  lua_settable(LuaScript.LuaState, Methods);
  lua_settable(LuaScript.LuaState, MethodTable);
  lua_setmetatable(LuaScript.LuaState, Methods);

// for each method that you want to register
  lua_pushcfunction(LuaScript.LuaState, lua<#ClassName#><#MethodName#>);
  lua_settable(LuaScript.LuaState, Methods);
// end of for each method

  lua_pop(LuaScript.LuaState, 2);
end;

 - Jeremy

"Help I suffer from the oxymoron Corporate Security."


> -------- Original Message --------
> Subject: Problem with userdata (metatable)
> From: "Anders Bergh" <anders@anders1.org>
> Date: Wed, April 12, 2006 8:25 am
> To: "Lua list" <lua@bazar2.conectiva.com.br>
> 
> Hi!
> 
> I'm using Lua 5.1 and I've been trying to add my own userdata type. It
> works except I couldn't get methods working. I've been reading the
> chapter in the first edition of pil and
> http://lua-users.org/wiki/UserDataWithPointerExample.
> 
> Here's the code I use:
> 
> static const luaL_reg llua_user_f[] = {
>   /* Functions */
>   {"FindByNick", llua_user_FindByNick},
> 
>   /* Methods */
>   {"GetNick", llua_user_GetNick},
>   {NULL, NULL}
> };
> 
> /* Metatable */
> static const luaL_reg llua_user_m[] = {
>   {"__tostring", llua_user_tostring},
>   {NULL, NULL}
> };
> 
> int lluaopen_user (lua_State *L) {
>   luaL_openlib(L, "user", llua_user_f, 0);
>   luaL_newmetatable(L, TYPE);
>   luaL_openlib(L, 0, llua_user_m, 0); /* mt */
> 
>   lua_pushliteral(L, "__index");
>   lua_pushvalue(L, -3);
>   lua_rawset(L, -3);
> 
>   lua_pushliteral(L, "__metatable");
>   lua_pushvalue(L, -3);
>   lua_rawset(L, -3);
> 
>   lua_pop(L, 1);
>   return 1;
> }
> 
> When I use "user:GetNick()" in Lua, I get the error: attempt to index
> field '?' (a nil value).
> 
> getmetatable(user) returns nil, tostring(user) returns "user:
> 0x815598c". What exactly am I doing wrong?
> 
> Anders