[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Strange userdata metatable behavior in C API
- From: dormando <dormando@...>
- Date: Sat, 02 Jun 2007 23:12:42 -0700
Hey,
I've been fighting with a nasty bug in the C API for a soon-to-be-GPL'ed
project o' mine... for several hours, and I'm wholly stuck. The problem
is pretty easy to illustrate:
in lua: (myp.listener and myp.new_handshake_pkt are C calls)
listen = myp.listener("127.0.0.1", 5500)
lmt = getmetatable(listen)
print("listener type", getmetatable(listen))
hs_pkt = myp.new_handshake_pkt()
print("Good", getmetatable(hs_pkt), lmt)
print("Bad", getmetatable(listen), getmetatable(hs_pkt))
print("Built a new handshake packet!", type(hs_pkt),
hs_pkt:protocol_version(),
hs_pkt:server_version())
print("listener data: ", listen:id(), listen:listener())
output:
listener type table: 0x519320
Good table: 0x519510 table: 0x519320
Bad table: 0x519510 table: 0x519510
Built a new handshake packet! userdata 10 blah
Could not run lua initializer: toast.lua:26: attempt to call method 'id'
(a nil value)
so, I do:
obj1 = c_func1()
obj2 = c_func2()
... and now obj1 has obj2's metatable :(
Stuff I've ruled out:
- Swapping the order of the object inits just swaps who gets who's metatable
- On my C end GDB is showing that I'm fetching the correct metatables
and setting them (it appears!) correctly. The correct pointers are being
used, etc.
- I'm not leaking stack vars
- I'm not overwriting the global metatable (should be illustrated by the
lmt = getmetatable(listen) up there
- This won't be true for the whole program, but obj1 and obj2 use
_completely_ different code paths for generating their objects.
- They don't appear to be garbage collected.
- obj1 and obj2 don't contain the same userdata, they don't == each
other from within lua, and aren't returning the same pointers into C.
The basic method used to create them in C:
(init p to something)
lua_pushlightuserdata(L, p);
luaL_getmetatable(L, type);
lua_setmetatable(L, -2);
return 1;
The metatables are "myp.conn" and "myp.handshake" - and are being
initialized during startup. Nothing edits the metatables by the time my
lua file is called.
Using lua 5.1.2 under linux, gcc 4.1.2. The point of this is to bind lua
objects over C structs. I've been very successful with one object at a
time... My custom metatable __index works fine, my generic C accessors
work fine, etc. These objects fully work as long as I'm not creating
another object after the first one.
I'm really itching to get this working, if anyone has any insight as to
what I might try to debug this, or if there's anything obvious I can check.
Thanks,
-Dormando