lua-users home
lua-l archive

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

Hi Andrew,

I just want to chime in and thank you for your detailed response. I
have been lurking here for a while, and have a similar project I have
in the works...your detailed answer...well answered a bunch of
questions I have had for a while.

Thanks for taking the time to write it.

Steve Wiseman

On Sat, Nov 16, 2013 at 9:46 PM, Andrew Starks <> wrote:
> Hey Geoff,
> I'll comment on some things here, directly:
> On Sat, Nov 16, 2013 at 3:34 PM, Geoff Smith <> wrote:
>> Hello Andrew
>> Thanks again for trying to assist,  I think we just proved its tricky to
>> formulate a clear question on a mailing list and to understand a partially
>> complete piece of code out of context.
>> Let me try to clarify the question again
>> I want to be able to call a fixed name Lua function on my btn userdata
>> instance.
>> btn1 = newButton(x,y, etc)
>> function btn1:action()
>>       print("this button was pressed")
>> end
>> The code I posted I have tested and works for assorted C functions and the
>> garbage collection, __tostring etc.
> Right. That's because your userdata has a shared metatable. That makes sense.
>> But for the Lua side btn:action() function  I cant get a reference to it to
>> call it via a pcall. That's the one thing that I am stuck on
> Not the way that you're doing it, correct. That's because when the
> callback happens in C, you don't have any stack. All you have (through
> your global) is a lua_State and a C pointer (the argument passed into
> the C callback).
>> Your solution below didn't even mention an "action" string, so it ignored
>> the bit I am stuck on.
> You're right, although my example led you directly to the solution. It
> was the most important part and then the fields - to - function part
> was the trivial part. You can't skip past the importance of linking
> your callback's argument to a reference that points to the userdata
> that Lua has.
> That is critical to understand: the C pointer to your object is the
> argument that your callback receives. This is the token that you have
> to reference your userdata object. In C, you cannot hold on to any lua
> data, unless you're accessing it from the stack. So, this is
> impossible to do, given only a C pointer... unless you use
> lightuserdata.
>> Also I didn't explain clearly but   pToObject  is a ptr to the button object
>> in my C side graphics library, Lua doesn't need to know about that so
>> pushing it on the stack cant be correct.
> No. This is the key. It is absolutely correct. You have to use this.
> Otherwise, you'll have to reinvent some way to track the object and
> find it in the registry, but it's just dumb to do it any other way.
> Do as I wrote. Push the pointer onto the stack by making a light
> userdata object. Then lua_pushvalue the userdata object to the top of
> the stack. Then lua_settable that into a table in your registry.
> This is your yellowbrickroad back to your userdata and it is the
> non-trivial part of your problem. The last part of your problem can be
> solved in any standard lua way that you want it to be solved.
>>  `pToUserdata`.  is the ptr to the btn1 userdata in my example
> As long as it is on the stack, yes.
>>>  but the name you've given it suggests a disturbing misunderstanding
>> its a ptr to a userdata block for that specific instance, so I didn't see
>> why you thought it implied a misunderstanding ?
> The point I was making is that you're always going to get a void *
> when you call newuserdata or checkuserdata. I was anticipating that
> you were expecting that you could later retrieve the userdata by
> knowing this value. In looking at your code, I don't see that, so
> you're right, you aren't making that mistake, as far as I see.
> It looks like you're using Lua 5.1. If that's the case, then uservalue
> is not an option for you.
> In that case, you need to manipulate the userdata's environment to
> include a callback table or make a unique metatable for each userdata
> object.  Since you've already abstracted luaL_checkudata into your
> checkUserdataButton function, I'd go this route.
> So, in your constructor, you need to make a new metatable for every
> userdata object and overload __index so that it points to your
> metatable and __newindex so that it adds the fields to the UD's
> metatable, since lua will be none too pleased with your luser tarting
> up your userdata with fields.
> Hopefully this is helpful. Sorry for all of the noise and let me know
> what you end up with!
> -Andrew