lua-users home
lua-l archive

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


Awesome, it works now! Thank you for all help!

Here's the working code, if anyone's interested:

int lluaopen_user (lua_State *L) {
  luaL_newmetatable(L, TYPE);

  lua_pushstring(L, "__index");
  lua_pushvalue(L, -2);
  lua_settable(L, -3);

  luaL_openlib(L, NULL, llua_user_m, 0);
  luaL_openlib(L, "user", llua_user_f, 0);
  return 1;
}

static const luaL_reg llua_user_f[] = {
  {"FindByNick", llua_user_FindByNick},
  {NULL, NULL}
};

static const luaL_reg llua_user_m[] = {
  {"__tostring", llua_user_tostring},
  {"GetNick", llua_user_GetNick},
  {NULL, NULL}
};

struct user *llua_checkuser (lua_State *L, int index) {
  struct user *user_ptr;
  luaL_checktype(L, index, LUA_TUSERDATA);
  user_ptr = *(struct user**)luaL_checkudata(L, index, TYPE);
  if (user_ptr == NULL) luaL_typerror(L, index, TYPE);
  return user_ptr;
}

struct user *llua_pushuser (lua_State *L, struct user *user_ptr) {
  struct user **l_user = (struct user**)lua_newuserdata(L,
sizeof(struct user*));
  *l_user = user_ptr;
  luaL_getmetatable(L, TYPE);
  lua_setmetatable(L, -2);
  return l_user;
}

On 4/12/06, jdarling@eonclash.com <jdarling@eonclash.com> wrote:
> Now we get into where LUA gets confusing to me :).  If you use
> newuserdata then you will recieve a blank block of memeory that you
> should use for your object.  So if for example you have a TMyClass you
> might think that the following would work:
>
> var
>   MyInst : TMyClass;
>   pData  : Pointer;
> begin
>   MyInst := TMyClass.Create;
>   pData := lua_newuserdata(LuaState, SizeOf(Pointer));
>   pData^ := MyInst;
> end;
>
> BUT IT WONT!  Instead you would have to do something like this:
>
> var
>   MyInst : TMyClass;
>   pData  : Pointer;
> begin
>   MyInst := lua_newuserdata(LuaState, SizeOf(Pointer));
>   MyInst.InitInstance(nil);
> end;
>
> The reason is that when you use newuserdata you are telling LUA to
> allocate your memory for you.  Also if you use it this way then you
> have to have an __gc method in your metatable.
>
> What I do instead is push my self pointer onto the LUA table that
> represents my object.  Something as such:
>
> function new_<#ClassName#>(L:Plua_State): Integer; cdecl;
> var
>   c : <#ClassName#>;
> begin
>   result := nil;
>   if lua_type(L, 1) <> LUA_TTABLE then
>     lua_remove(L, 1): // Hack to allow TMyClass:new() or TMyClass.new to
> work
>   c := <#ClassName#>.Create;
>   LuaSetTableLightUserData(L, 1, '_Self', c);
>   luaL_getmetatable(L, Lua<#ClassName#>ClassName);
>   lua_setmetatable(L, -2);
>   result := 1;
> end;
>
> This in turn sets up a new entery in the object table for each instance
> with the value of _Self being the pointer to c.  Then I have a check
> method:
>
> function Check<#ClassName#>(L:Plua_State; Idx : Integer): <#ClassName#>;
> begin
>   result := nil;
>   if lua_type(L, Idx) = LUA_TTABLE then
>     result := LuaGetTableLightUserData(L, Idx, '_Self')
>   else
>     lua_typeerror(L, Idx, Lua<#ClassName#>ClassName);
> end;
>
> And make use of it as:
>
> function Lua<#ClassName#><#MethodName#>(L: Plua_State):integer; cdecl;
> var
>   c : <#ClassName#>;
> begin
>   c := Check(L, 1); // Get the reference
>   lua_remove(L, 1); // remove the temporary operating table so operators
> are in normal 1..x order
>   c.<#MethodName#>([Oper0..OperN]);
>   result := MethodResultCount;
> end;
>
> Above is kinda psudo code as is everything, the Lua parts are real, the
> rest is from my template I use to import objects from Delphi into LUA.
> Again take a look at LUNA and the tutorial that was posted here a few
> days ago in a post entitled:  Lua api windows tutorial by Jeff Jacob.
> They are good references.
>
>  - Jeremy
>
> "Help I suffer from the oxymoron Corporate Security."
>
>
> > -------- Original Message --------
> > Subject: Re: Problem with userdata (metatable)
> > From: "Anders Bergh" <anders@anders1.org>
> > Date: Wed, April 12, 2006 1:47 pm
> > To: "Lua list" <lua@bazar2.conectiva.com.br>
> >
> > Looks like methods work now, but I have another problem. When I use
> > "user:GetNick()" in Lua, it segfaults.
> >
> > All I get are pointers to users, and I create the userdata with:
> >
> > struct user *llua_pushuser (lua_State *L, struct user *user_ptr) {
> >   struct user *l_user = (struct user*)lua_newuserdata(L, sizeof(struct user*));
> >   l_user = user_ptr;
> >   luaL_getmetatable(L, TYPE);
> >   lua_setmetatable(L, -2);
> >   return l_user;
> > }
> >
> > Now when I use "PrintUserInfo(llua_checkuser(L, 1))" in the GetNick C
> > function it segfaults:
> >
> > PrintUserInfo: 0x8158a4c
> >  -> nick:
> >  -> numeric: ¸hï·
> >  -> oper: 96
> > Segmentation fault
> >
> > Here's my "llua_checkuser" function:
> >
> > struct user *llua_checkuser (lua_State *L, int index) {
> >   struct user *user_ptr;
> >   luaL_checktype(L, index, LUA_TUSERDATA);
> >   user_ptr = (struct user*)luaL_checkudata(L, index, TYPE);
> >   if (user_ptr == NULL) luaL_typerror(L, index, TYPE);
> >   return user_ptr;
> > }
> >
> > I think 0x8158a4c points to something inside Lua, and not the user
> > pointer... I hope I make sense. Is there anything I'm doing wrong
> > here?
> >
> > Anders
> >
> > On 4/12/06, jdarling@eonclash.com <jdarling@eonclash.com> wrote:
> > > > TYPE is defined as "L2.user".
> > >
> > > Unless something has changed you can't use dot notation in your libarary
> > > or variable names.
> > >
> > > I use __index and __newindex to "catch" object properties __index is
> > > read (or get) and __newindex is write (or set).  Instead they should be
> > > set to the meta-table (as your doing).  My guess (and at this point its
> > > only a guess) is that the dot notation in your table name is throwing
> > > things off.  Try "L2_user" instead of "L2.user" and see what happens.
> > >
> > > >
> > > > The GD binding example code works in 5.1 (the methods work), but they
> > > > don't in my code so there must be something I'm doing differently...
> > > > but what? Reading your Delphi code didn't really help me (I don't have
> > > > a C function for __index, and I couldn't exactly figure out what to do
> > > > instead). Should I open the library in a certain way?
> > > >
> > > > Anders
> > >
> > >
> > >
>
>