lua-users home
lua-l archive

Re: Lua C API : How to have an "object" deriving form another one.

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


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.

AltStyle によって変換されたページ (->オリジナル) /