Add a wuffs_base__vtable type
diff --git a/internal/cgen/base/core-public.h b/internal/cgen/base/core-public.h
index c823099..e8094c7 100644
--- a/internal/cgen/base/core-public.h
+++ b/internal/cgen/base/core-public.h
@@ -132,6 +132,11 @@
   uint8_t private_impl;
 } wuffs_base__utility;
 
+typedef struct {
+  const char* vtable_name;
+  const void* function_pointers;
+} wuffs_base__vtable;
+
 // --------
 
 // See https://github.com/google/wuffs/blob/master/doc/note/statuses.md
diff --git a/internal/cgen/cgen.go b/internal/cgen/cgen.go
index dbc87dd..1f568c6 100644
--- a/internal/cgen/cgen.go
+++ b/internal/cgen/cgen.go
@@ -762,6 +762,7 @@
 	if n.Classy() {
 		b.writes("uint32_t magic;\n")
 		b.writes("uint32_t active_coroutine;\n")
+		b.writes("wuffs_base__vtable null_vtable;\n")
 		b.writes("\n")
 	}
 
diff --git a/internal/cgen/data.go b/internal/cgen/data.go
index 69310d1..720448d 100644
--- a/internal/cgen/data.go
+++ b/internal/cgen/data.go
@@ -67,7 +67,7 @@
 	"d \"work buffer\".\n//\n// For more detail, see:\n// https://github.com/google/wuffs/blob/master/doc/note/initialization.md\n#define WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED \\\n  ((uint32_t)0x00000002)\n\n" +
 	"" +
 	"// --------\n\n// wuffs_base__empty_struct is used when a Wuffs function returns an empty\n// struct. In C, if a function f returns void, you can't say \"x = f()\", but in\n// Wuffs, if a function g returns empty, you can say \"y = g()\".\ntypedef struct {\n  // private_impl is a placeholder field. It isn't explicitly used, except that\n  // without it, the sizeof a struct with no fields can differ across C/C++\n  // compilers, and it is undefined behavior in C99. For example, gcc says that\n  // the sizeof an empty struct is 0, and g++ says that it is 1. This leads to\n  // ABI incompatibility if a Wuffs .c file is processed by one compiler and\n  // its .h file with another compiler.\n  //\n  // Instead, we explicitly insert an otherwise unused field, so that the\n  // sizeof this struct is always 1.\n  uint8_t private_impl;\n} wuffs_base__empty_struct;\n\nstatic inline wuffs_base__empty_struct  //\nwuffs_base__make_empty_struct() {\n  wuffs_base__empty_struct ret;\n  ret.private_impl = 0;\n  return ret;\n}\n\n// wuffs_base__utility is" +
-	" a placeholder receiver type. It enables what Java\n// calls static methods, as opposed to regular methods.\ntypedef struct {\n  // private_impl is a placeholder field. It isn't explicitly used, except that\n  // without it, the sizeof a struct with no fields can differ across C/C++\n  // compilers, and it is undefined behavior in C99. For example, gcc says that\n  // the sizeof an empty struct is 0, and g++ says that it is 1. This leads to\n  // ABI incompatibility if a Wuffs .c file is processed by one compiler and\n  // its .h file with another compiler.\n  //\n  // Instead, we explicitly insert an otherwise unused field, so that the\n  // sizeof this struct is always 1.\n  uint8_t private_impl;\n} wuffs_base__utility;\n\n" +
+	" a placeholder receiver type. It enables what Java\n// calls static methods, as opposed to regular methods.\ntypedef struct {\n  // private_impl is a placeholder field. It isn't explicitly used, except that\n  // without it, the sizeof a struct with no fields can differ across C/C++\n  // compilers, and it is undefined behavior in C99. For example, gcc says that\n  // the sizeof an empty struct is 0, and g++ says that it is 1. This leads to\n  // ABI incompatibility if a Wuffs .c file is processed by one compiler and\n  // its .h file with another compiler.\n  //\n  // Instead, we explicitly insert an otherwise unused field, so that the\n  // sizeof this struct is always 1.\n  uint8_t private_impl;\n} wuffs_base__utility;\n\ntypedef struct {\n  const char* vtable_name;\n  const void* function_pointers;\n} wuffs_base__vtable;\n\n" +
 	"" +
 	"// --------\n\n// See https://github.com/google/wuffs/blob/master/doc/note/statuses.md\ntypedef struct {\n  const char* repr;\n\n#ifdef __cplusplus\n  inline bool is_complete() const;\n  inline bool is_error() const;\n  inline bool is_note() const;\n  inline bool is_ok() const;\n  inline bool is_suspension() const;\n  inline const char* message() const;\n#endif  // __cplusplus\n\n} wuffs_base__status;\n\n// !! INSERT wuffs_base__status names.\n\nstatic inline wuffs_base__status  //\nwuffs_base__make_status(const char* repr) {\n  wuffs_base__status z;\n  z.repr = repr;\n  return z;\n}\n\nstatic inline bool  //\nwuffs_base__status__is_complete(const wuffs_base__status* z) {\n  return (z->repr == NULL) || ((*z->repr != '$') && (*z->repr != '#'));\n}\n\nstatic inline bool  //\nwuffs_base__status__is_error(const wuffs_base__status* z) {\n  return z->repr && (*z->repr == '#');\n}\n\nstatic inline bool  //\nwuffs_base__status__is_note(const wuffs_base__status* z) {\n  return z->repr && (*z->repr != '$') && (*z->repr != '#');\n}\n\nstatic inline bool  //\nwu" +
 	"ffs_base__status__is_ok(const wuffs_base__status* z) {\n  return z->repr == NULL;\n}\n\nstatic inline bool  //\nwuffs_base__status__is_suspension(const wuffs_base__status* z) {\n  return z->repr && (*z->repr == '$');\n}\n\n// wuffs_base__status__message strips the leading '$', '#' or '@'.\nstatic inline const char*  //\nwuffs_base__status__message(const wuffs_base__status* z) {\n  if (z->repr) {\n    if ((*z->repr == '$') || (*z->repr == '#') || (*z->repr == '@')) {\n      return z->repr + 1;\n    }\n  }\n  return z->repr;\n}\n\n#ifdef __cplusplus\n\ninline bool  //\nwuffs_base__status::is_complete() const {\n  return wuffs_base__status__is_complete(this);\n}\n\ninline bool  //\nwuffs_base__status::is_error() const {\n  return wuffs_base__status__is_error(this);\n}\n\ninline bool  //\nwuffs_base__status::is_note() const {\n  return wuffs_base__status__is_note(this);\n}\n\ninline bool  //\nwuffs_base__status::is_ok() const {\n  return wuffs_base__status__is_ok(this);\n}\n\ninline bool  //\nwuffs_base__status::is_suspension() const {\n  return wuffs_base" +
diff --git a/release/c/wuffs-unsupported-snapshot.c b/release/c/wuffs-unsupported-snapshot.c
index 98f6e6f..438a202 100644
--- a/release/c/wuffs-unsupported-snapshot.c
+++ b/release/c/wuffs-unsupported-snapshot.c
@@ -154,6 +154,11 @@
   uint8_t private_impl;
 } wuffs_base__utility;
 
+typedef struct {
+  const char* vtable_name;
+  const void* function_pointers;
+} wuffs_base__vtable;
+
 // --------
 
 // See https://github.com/google/wuffs/blob/master/doc/note/statuses.md
@@ -2623,6 +2628,7 @@
   struct {
     uint32_t magic;
     uint32_t active_coroutine;
+    wuffs_base__vtable null_vtable;
 
     uint32_t f_state;
     bool f_started;
@@ -2740,6 +2746,7 @@
   struct {
     uint32_t magic;
     uint32_t active_coroutine;
+    wuffs_base__vtable null_vtable;
 
     uint32_t f_state;
 
@@ -2882,6 +2889,7 @@
   struct {
     uint32_t magic;
     uint32_t active_coroutine;
+    wuffs_base__vtable null_vtable;
 
     uint32_t f_bits;
     uint32_t f_n_bits;
@@ -3077,6 +3085,7 @@
   struct {
     uint32_t magic;
     uint32_t active_coroutine;
+    wuffs_base__vtable null_vtable;
 
     uint32_t f_set_literal_width_arg;
     uint32_t f_literal_width;
@@ -3309,6 +3318,7 @@
   struct {
     uint32_t magic;
     uint32_t active_coroutine;
+    wuffs_base__vtable null_vtable;
 
     uint32_t f_width;
     uint32_t f_height;
@@ -3623,6 +3633,7 @@
   struct {
     uint32_t magic;
     uint32_t active_coroutine;
+    wuffs_base__vtable null_vtable;
 
     bool f_ignore_checksum;
 
@@ -3789,6 +3800,7 @@
   struct {
     uint32_t magic;
     uint32_t active_coroutine;
+    wuffs_base__vtable null_vtable;
 
     bool f_bad_call_sequence;
     bool f_header_complete;