[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Problem with userdata (metatable)
- From: "Anders Bergh" <anders@...>
- Date: Wed, 12 Apr 2006 22:07:37 +0200
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
> > >
> > >
> > >
>
>