[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Another userdata question
- From: Sean Conner <sean@...>
- Date: Wed, 13 Nov 2013 22:59:01 -0500
It was thus said that the Great Geoff Smith once stated:
> I am really hoping someone could help me with this question please as I am
> totally stuck on it for now.
>
> I am trying to implement a userdata via the C API, to give me this type
> of functionality
>
> btn1 = graphics.newButton(x,y,width,ht, "pressMe")
> btn1:setText("Different Text")
> btn1:setFont("Arial")
>
> That's OK I think I have got that figured out and largely working, but the
> next thing I want to do is call a user defined Lua action function on the
> button instance. For example
>
> In Lua
>
> function btn1:action(someArbitrayParamBackFromC)
> print("ouch someone just poked btn1")
> end
>
> How can I call that Lua button instance function from C when I have
> detected the key is pressed ?
The method I use [1] runs along these lines:
static int Xdisplay_window(lua_State *L)
{
Window *window;
/* ... a bunch of code ... */
window = lua_newuserdata(L,sizeof(Window));
*window = XCreateWindow(...);
/* use this table for __index and __newindex */
lua_createtable(L,0,0);
lua_pushvalue(L,-1);
lua_setfield(L,-1,"__index");
lua_pushvalue(L,-1);
lua_setfield(L,-2,"__newindex");
/* populate predefined functions into this table */
luaL_register(L,NULL,Xwindow_metatable);
/* set as the metatable for our userdata */
lua_setmetatable(L,-2);
}
By giving each created window its own distinct metatable, I can attach
arbitrary Lua values to the "window". So, for instance, in Lua, I can do:
window = display:window(...)
window.somedata = 3
window.callback = function() ... end
So then, I could do the following:
function window:action()
print("Hey! Somebody hit me!")
end
And in C code, when I detected that the window has been acted upon:
/*-----------------------------------------------------------------
; can't use luaL_checkudata() since we have a custom metatable. I
; have a work around for it, but I'm skipping that code as it would
; otherwise clutter the example.
;-------------------------------------------------------------------*/
Window *window = ... /* code to get object */;
if (luaL_getmetafield(L,-1,"action") == 0)
return; /* no action defined, just ignore for now */
lua_pushvalue(L,-2); /* push window parameter into place */
lua_call(L,1,0); /* call function with window as a parameter */
(or use lua_pcall()---depends on how you want to handle potential errors)
Yes, this does mean you can't have a single instance of a metatable for
all the objects, but for me, the ability to treat the userdata as a Lua
table outweighs the downsides.
-spc
[1] A (private so far) project to create X11 bindings [2] to Lua. It's
more of a instructional thing for me and isn't really meant for
public consumption. At the very least, you would need to understand
Xlib to even use it.
[2] Xlib level. About as low as you can go without touching the actual
X protocol.