lua-users home
lua-l archive

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

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
> 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!