lua-users home
lua-l archive

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


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
> >
> >
> >