[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Lua C API : How to have an "object" deriving form another one.
- From: Sean Conner <sean@...>
- Date: Fri, 22 May 2020 20:47:28 -0400
It was thus said that the Great Laurent FAILLIE once stated:
> Hello,
> I'm working to a graphical framework in C dealing with Cairo graphics.
> I'm creating an object named SelDCSurface that deals with Cairo's surface
> https://github.com/destroyedlolo/Selene/blob/v6/src/SelPlugins/DRMCairo/SelDCSurface.c
> Some methods are attached to it using luaL_setfuncs() or luaL_register().
> Now, I'm working on SelDCImageSurface which is basically an extension of SelDCSurface : it has to know all methods of SelDCSurface plus its own.
> 1/ How to do that ?I guess I can use luaL_setfuncs() or luaL_register() more than once on the same object, to add additional methods, isn't it ?
I have a "work-when-I-get-to-it-in-progress" wrapping Xlib [1] and I
solved that problem by just including the additional methods into the table:
static const luaL_Reg xpixmap_meta[] =
{
{ "__index" , x___index } ,
{ "__newindex" , x___newindex } ,
{ "__gc" , xpixmap___gc } ,
{ "__tostring" , xpixmap___tostring } ,
{ "copy" , xdrawable_copy } ,
{ "draw_arc" , xdrawable_draw_arc } ,
{ "draw_fill_arc" , xdrawable_draw_fill_arc } ,
{ "draw_fill_rect" , xdrawable_draw_fill_rect } ,
{ "draw_line" , xdrawable_draw_line } ,
{ "draw_point" , xdrawable_draw_point } ,
{ "draw_rect" , xdrawable_draw_rect } ,
{ "draw_string" , xdrawable_draw_string } ,
{ "gc" , xdrawable_gc } , /* Graphics Context */
{ NULL , NULL }
};
static const luaL_Reg xwindow_meta[] =
{
{ "__index" , x___index } ,
{ "__newindex" , x___newindex } ,
{ "__gc" , xwindow___gc } ,
{ "__tostring" , xwindow___tostring } ,
{ "attributes" , xwindow_attributes } ,
{ "background" , xwindow_background } ,
{ "checkevent" , xwindow_checkevent } ,
{ "clear" , xwindow_clear } ,
{ "copy" , xdrawable_copy } ,
{ "cursor" , xwindow_cursor } ,
{ "dimensions" , xwindow_dimensions } ,
{ "draw_arc" , xdrawable_draw_arc } ,
{ "draw_fill_arc" , xdrawable_draw_fill_arc } ,
{ "draw_fill_rect" , xdrawable_draw_fill_rect } ,
{ "draw_line" , xdrawable_draw_line } ,
{ "draw_point" , xdrawable_draw_point } ,
{ "draw_rect" , xdrawable_draw_rect } ,
{ "draw_string" , xdrawable_draw_string } ,
{ "focus" , xwindow_focus } ,
{ "gc" , xdrawable_gc } ,
{ "hide" , xwindow_hide } ,
{ "listproperties" , xwindow_listproperties } ,
{ "lower" , xwindow_lower } ,
{ "move" , xwindow_move } ,
{ "moveresize" , xwindow_moveresize } ,
{ "raise" , xwindow_raise } ,
{ "resize" , xwindow_resize } ,
{ "seticon" , xwindow_seticon } ,
{ "seticonname" , xwindow_seticonname } ,
{ "setname" , xwindow_setname } ,
{ "show" , xwindow_show } ,
{ "showsub" , xwindow_showsub } ,
{ "sizehints" , xwindow_sizehints } ,
{ "wmhints" , xwindow_wmhints } ,
{ "wmprotocol" , xwindow_wmprotocol } ,
{ NULL , NULL }
};
I suppose multiple tables and using luaL_setfuncs()/luaL_register()
multiple times could work. In my case, it would have to be one table for
the metamethods, and one each for the non-metamethods to be included.
> 2/ my main concern is the function used if "self" object has the right type
> I.E. for method
[ snip ]
> The problem, is when called from a SelDCImageSurface object, GetSize() will still call checkSelDCSurface() which fails as facing a "SelDCImageSurface" and not a "SelDCSurface".
> Any smart way to avoid that ?
I ended up writing my own functions to handle an object that could be
different types:
static bool XL_isudata(lua_State *const L,int idx,const char *const tname)
{
assert(L != NULL);
assert(idx != 0);
assert(tname != NULL);
void *p = lua_touserdata(L,idx);
if (p != NULL)
{
if (lua_getmetatable(L,idx))
{
const char *type;
bool rc;
lua_getfield(L,-1,"_TYPE");
type = lua_tostring(L,-1);
rc = strcmp(type,tname) == 0;
lua_pop(L,2);
return rc;
}
}
return false;
}
static void *XL_multiudata(lua_State *const L,int idx, ... )
{
void *tname;
va_list ap;
assert(L != NULL);
assert(idx != 0);
va_start(ap,idx);
while((tname = va_arg(ap,void *)) != NULL)
{
if (XL_isudata(L,idx,tname))
{
va_end(ap);
return lua_touserdata(L,idx);
}
}
va_end(ap);
luaL_error(L,"wrong type of data");
return NULL;
}
And to use it:
Drawable drawable = XL_multiudata(L,1,XLUA_WINDOW,XLUA_PIXMAP,NULL);
That's how I solved the issue.
-spc
[1] No, it's not in any state to release right now and is mostly for my
own amusement.