lua-users home
lua-l archive

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


Sam,

I really appreciate your feedback, but it's not helping. You are giving me concepts assuming that I already understand them. For example, how do I return userdata from the Cfunction to the script so that it will not "become unreferenced immediately after I create it"?

The missing concept in precisely what has to happen for the userdata I've created to be referenced? Do I push the userdata ptr onto the return stack using lua_pushlightuserdata( ptr ) and then, in the script, set a table element to the return value? I tried that and then set the table element to nil and called collectgarbage(), but my Cfunction garbage collector did not get called.

Michael

----- Original Message ----- From: "Sam Roberts" <vieuxtech@gmail.com>
To: "Lua list" <lua@bazar2.conectiva.com.br>
Sent: Saturday, August 15, 2009 1:34 PM
Subject: Re: how does GC work with complex expressions using metamethods?


On Sat, Aug 15, 2009 at 12:51 PM, Michael
Newberry<mnewberry@mirametrics.com> wrote:
OK, Here's what I have come up with (but it doesn't work):

When the script starts, the app executes this new function:

void SetupCDataGC( struct lua_State* L ) // setup garbage collection
{
luaL_newmetatable( L, "CData_type" ); // create metatable for CData
lua_pushstring( L, "__gc" );
lua_pushcfunction( L, CDataDelete );
lua_settable( L, -3 );
}

The new userdata delete function is declared like this:

int CDataDelete( struct lua_State* L )
{
// deletion stuff
return 0;
}

When the lua script creates the CData table (a lua "class"), it calls a
CFunction to create the C++ object (existing code). Inside that function, I
added the following code:

CData** ptr = (CData**)lua_newuserdata( L, sizeof(CData*) );
*ptr = pData;
luaL_getmetatable( L, "CData_type" );
lua_setmetatable( L, -2 );

lua_pushlightuserdata( L, pData ); // return the C++ object's pointer
to the script
return 1;

You are creating userdata, but not returning it, instead just
returning lightuserdata. This can't work.

Not seeing all your code, but since you aren't returning the userdata,
it will become unreferenced immediately after you create it, and
garbage collected sometime later, causing your lightuserdata to point
to a deleted object at some random future time.

I think what you have done in the past is just bind a bunch of c fns
into lua, wrap them in a lua object/table, make a table key that is
light userdata, and write "methods" in lua that pass in that light
userdata. Once you get userdata working, you'll find that it offers
much more direct and useful ways of doing all that, but you may have
to throw away some of your existing thinking.

Anyhow, for debugging, I suggest starting from scratch, use the
userdata as your lua "object", not a table, and start implementing
from there. Once you've got it working, integrate back into your app.

Also, remember to call collectgarbage() to force a gc cycle, otherwise
you might have to wait a while, even for lua to exit, before gc
happens. Put a printf() in your __gc so you can watch the collection
happen.

Also, take a look at debug.getmetatable(), it will help you inspect
your userdata to verify it's metatable has a __gc.

Cheers,
Sam