The Allegro Wiki is migrating to github at

Proposed vtables

From Allegro Wiki
Jump to: navigation, search


VTables (definition) are used in Allegro 4.2 for objects like bitmaps, video drivers and system drivers. They enable the user to use the same functions on an object, even though its implementation may be different (e.g. blitting memory bitmaps vs video bitmaps)

Beginning in Allegro 4.2 (with PACKFILE), vtables are also going to be used more for plugins.


At the moment, a vtable is a static C-structure. This is inadequate because it can't handle changes to the vtable structure. For example, if a function were added or changed in the vtable, it would break all plugins.


The proposals are:

A. String-based static tables

<highlightSyntax language="cpp"> static const AL_VTABLE_1_0 my_vtable[] = {

              { "init",  1.0, my_init  },
              { "exit",  1.0, my_exit  },
              { "vsync", 1.0, my_vsync },
              { NULL,      0, NULL     }
      GFX_VTABLE *al_vtable = create_gfx_vtable();
      register_gfx_vtable_1_0(al_vtable, my_vtable);

B. String based register functions

<highlightSyntax language="cpp">GFX_VTABLE *al_vtable = create_gfx_vtable(); register_gfx_vtable_1_0(al_vtable, "init", 1.0, my_init); register_gfx_vtable_1_0(al_vtable, "exit", 1.0, my_exit); register_gfx_vtable_1_0(al_vtable, "vsync", 1.0, my_vsync);


or something cleaner: <highlightSyntax language="cpp">// in header

  1. define AL_MAKE_VERSION(a, b, c) (((a)<<16) | ((b)<<8) | (c))

// user code GFX_VTABLE *al_vtable = create_gfx_vtable(AL_MAKE_VERSION(1, 0, 0)); register_gfx_vtable(al_vtable, "init", my_init); register_gfx_vtable(al_vtable, "exit", my_exit); register_gfx_vtable(al_vtable, "vsync", my_vsync);


C. Enum based register functions

<highlightSyntax language="cpp">AL_VTABLE *vtable = al_create_vtable(version); al_register_vtable_func(vtable, FUNC_ID, my_func); al_register_finish(vtable);


D. Versioned static tables

How about this (partly DirectX-inspired) proposal? Start with the first version of the vtable. <highlightSyntax language="cpp"> typedef struct VTABLE_V1 {

       void (*some_method)(int blah);
   void register_vtable_v1(VTABLE_V1 *vtbl);

Drivers would statically fill in VTABLE_V1 instances, as they do now, with type checking.

Now say we want to add a new method to the vtable, and change the function signature of an existing method: <highlightSyntax language="cpp"> typedef struct VTABLE_V2 {

       void (*new_method)(blah);
       void (*some_method)(float blah);
   void register_vtable_v2(VTABLE_V2 *vtbl);

// register_vtable_v1() would need to adapt V1 vtables to V2:

   void register_vtable_v1(VTABLE_V1 *v1)
       VTABLE_V2 *v2 = allocate_v2_vtable();
       v2->v1_vtable = v1;
       v2->new_method = NULL;
       v2->some_method = v1_some_method_adaptor;

E. Static table register functions

<highlightSyntax language="cpp">static AL_DISPLAY_DRIVER drv;

  void _xwin_create_display_drivers(void)
     drv->init = _xwin_gfxdrv_init;
     drv->exit = _xwin_gfxdrv_exit;

F. 4.2.0 way.

Vtables are just simple, non-versioned structs, and can be statically initialized as well as dynamically updated.

<highlightSyntax language="cpp">static AL_DISPLAY_DRIVER drv;

  drv->init = _xwin_gfxdrv_init;
  drv->exit = _xwin_gfxdrv_exit;


Issues to consider

  • complexity and code-size vs. how many times vtables are likely to change
  • when 'adapting' a vtable, where do the pointers to 'old' entries come from
  • type safety
  • speed


solution type safe ABI compatible dynamic update votes (add your initials)
A No Yes No -
B No Yes Yes -
C No Yes Yes -
D Yes Yes No -
E Yes No No -
F Yes No Yes (this is what "won"... it simply was carried over to A5 without a vote)

Related Link