lua-users home
lua-l archive

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


2009/8/18 Chris Camacho <c.camacho@ntlworld.com>:
> well I'm totally lost now...
>
> cpBody *has* a metatable (__index is used for the methods) I even tried

cpBody has no metatable until you call lua_setmetatable. In your
previous email, you were indexing the userdata *before* assigning a
metatable to it.

> char buf[40];
> cpBody *bb = (cpBody *)lua_newuserdata(L, sizeof(cpBody));
> lua_pushvalue(L,-1);
> luaL_getmetatable(L, "cpBody");
> lua_setmetatable(L, -2);
>
> lua_pushstring(L,"__cpBody_ptrs");
> sprintf(buf,"%ld\0",(long)bb);
> lua_setfield(L,-2,buf);
>
> luaL_getmetatable(L, "cpBody");
> lua_setmetatable(L, -2);
> return bb;
>
>
> How am I missing your previous advice, are you able to
> explain in a clearer manner?

The principle was to store a reference to your userdata object (keep
in mind that all stack slots and table fields are merely references)
inside a weak table. In the example above there is no such weak table.
The principle was also to use the userdata address as a key, in the
form of a "light userdata" (which is a different Lua data type from
"userdata", cf. the manual), not as a string.

> how else would I index the cpBody* C pointer with the userdata instance
> in a table called __cpBody_ptrs  ?

Assuming __cpBody_ptrs is a global table with weak values (ask if you
don't know how to create it), you're clearly not using the Lua C API
correctly to put stuff in it. You seam to be using lua_pushstring
alone to get the global variable __cpBody_ptrs. To get a global
variable either use lua_getglobal, or lua_pushstring along with
lua_gettable.

Here is how to do it:

/* create the userdata */
cpBody *bb = (cpBody *)lua_newuserdata(L, sizeof(cpBody));
/* set the metatable */
luaL_getmetatable(L, "cpBody");
lua_setmetatable(L, -2);

/* push the weak table name */
lua_pushstring(L,"__cpBody_ptrs");
/* retrieve the weak table (I assume it's in the globals) */
lua_gettable(L, LUA_GLOBALSINDEX);
/* push the userdata adress as a light userdata, this is the key */
lua_pushlightuserdata(L, (void*)bb);
/* push a reference to the full userdata, this is the (weak) value */
lua_pushvalue(L, -3);
/* put the lightudata/fulludata pair into __cpBody_ptrs table (which
is on the stack) */
lua_settable(L, -3);
/* remove __cpBody_ptrs from the stack */
lua_pop(L, 1);

/* return bb so it get initialized. keep in mind that here the full
udata is still on the stack */
return bb;