lua-users home
lua-l archive

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


Hi Sean,

it's pretty clear, thanks a lot :)
My only drawback is I will have to add all child name in the mother class.

I keep it in mind if my solution to have a local variable is not managable.

Thanks

Laurent





Le samedi 23 mai 2020 à 02:48:24 UTC+2, Sean Conner <sean@conman.org> a écrit :


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.