読者です 読者をやめる 読者になる 読者になる

C、オブジェクト指向

設計、Object-Oriented Programming With ANSI-Cより

クラスに共通して使われる抽象クラスの定義

struct Class {
  size_t size;
  void * (* ctor) (void * self, va_list * app);
  void * (* dtor) (void * self);
  void * (* clone) (const void * self);
  int (* differ) (const void * self, const void * b);
};

Stringクラスの型の定義。コンパイル時に生成される。

struct String {
  const void * class; /* must be first */
  char * text;
};

static void * String_ctor (void * _self, va_list * app)
{
  struct String * self = _self;
  const char * text = va_arg(* app, const char *);
  self ―> text = malloc(strlen(text) + 1);
  assert(self ―> text);
  strcpy(self ―> text, text);
  return self;
}

// その他methodの定義が必要

static const struct Class _String = { // 構造体の初期化を使う、一回だけ作られる
  sizeof(struct String),
  String_ctor, String_dtor,
  String_clone, String_differ
};
const void * String = & _String;

new()の実装。new(String, "abc")として使う。

void * new (const void * _class, ...)
{
  const struct Class * class = _class; // クラスを抽象クラスにキャスト
  void * p = calloc(1, class ―> size); // サイズを読み込んで、メモリを確保
  assert(p);
  * (const struct Class **) p = class; // メモリ空間を抽象クラスにキャスト、オブジェクトの生成
  if (class ―> ctor)
  {
    va_list ap;
    va_start(ap, _class);
    p = class ―> ctor(p, & ap); // クラス固有のコンストラクタ、selfを返す
    va_end(ap);
  }
  return p;
}

mruby

シンプルで柔軟な配列を作りたい。mrubyのRArrayを参考に。
Ruby Hacking Guideも参考に。http://i.loveruby.net/ja/rhg/book/

mrubyのコピーライト(https://github.com/mruby/mruby/blob/master/include/mruby.h

mruby.h
typedef struct mrb_state {
  void *jmp;

  mrb_allocf allocf;

  mrb_value *stack;
  mrb_value *stbase, *stend;

  mrb_callinfo *ci;
  mrb_callinfo *cibase, *ciend;

  mrb_code **rescue;
  int rsize;
  struct RProc **ensure;
  int esize;

  struct RObject *exc;
  struct iv_tbl *globals;

  struct mrb_irep **irep;
  size_t irep_len, irep_capa;

  mrb_sym init_sym;
  struct RClass *object_class;
  struct RClass *class_class;
  struct RClass *module_class;
  struct RClass *proc_class;
  struct RClass *string_class;
  struct RClass *array_class;
  struct RClass *hash_class;

  struct RClass *float_class;
  struct RClass *fixnum_class;
  struct RClass *true_class;
  struct RClass *false_class;
  struct RClass *nil_class;
  struct RClass *symbol_class;

  struct RClass *kernel_module;
  struct heap_page *heaps;
  struct heap_page *sweeps;
  struct heap_page *free_heaps;
  size_t live; /* count of live objects */
  struct RBasic *arena[MRB_ARENA_SIZE];
  int arena_idx;

  enum gc_state gc_state; /* state of gc */
  int current_white_part; /* make white object by white_part */
  struct RBasic *gray_list; /* list of gray objects */
  struct RBasic *variable_gray_list; /* list of objects to be traversed atomically */
  size_t gc_live_after_mark;
  size_t gc_threshold;
  int gc_interval_ratio;
  int gc_step_ratio;
  int gc_disabled;

  mrb_sym symidx;
  struct kh_n2s *name2sym;      /* symbol table */
  struct kh_s2n *sym2name;      /* reverse symbol table */
#ifdef INCLUDE_REGEXP
  struct RNode *local_svar;/* regexp */
#endif

  struct RClass *eException_class;
  struct RClass *eStandardError_class;

  void *ud; /* auxiliary data */
} mrb_state;

array.h

struct mrb_shared_array {
  int refcnt;
  mrb_value *ptr;
  int len;
};

struct RArray {
  MRB_OBJECT_HEADER;
  int len;
  union {
    int capa;
    struct mrb_shared_array *shared;
  } aux;
  mrb_value *ptr;
};
value.h

:はビットフィールド。

enum mrb_vtype {
  MRB_TT_FALSE = 0,   /*   0 */
  MRB_TT_FREE,        /*   1 */
  MRB_TT_TRUE,        /*   2 */
  MRB_TT_FIXNUM,      /*   3 */
  MRB_TT_SYMBOL,      /*   4 */
  MRB_TT_UNDEF,       /*   5 */
  MRB_TT_FLOAT,       /*   6 */
  MRB_TT_OBJECT,      /*   7 */
  MRB_TT_CLASS,       /*   8 */
  MRB_TT_MODULE,      /*   9 */
  MRB_TT_ICLASS,      /*  10 */
  MRB_TT_SCLASS,      /*  11 */
  MRB_TT_PROC,        /*  12 */
  MRB_TT_ARRAY,       /*  13 */
  MRB_TT_HASH,        /*  14 */
  MRB_TT_STRING,      /*  15 */
  MRB_TT_RANGE,       /*  16 */
  MRB_TT_REGEX,       /*  17 */
  MRB_TT_STRUCT,      /*  18 */
  MRB_TT_EXCEPTION,   /*  19 */
  MRB_TT_MATCH,       /*  20 */
  MRB_TT_FILE,        /*  21 */
  MRB_TT_ENV,         /*  22 */
  MRB_TT_DATA,        /*  23 */
  MRB_TT_MAXDEFINE    /*  24 */
};

typedef struct mrb_value {
  union {
    mrb_float f;
    void *p;
    mrb_int i;
    mrb_sym sym;
  } value;
  enum mrb_vtype tt:8;
} mrb_value;
object.h
#define MRB_OBJECT_HEADER \
  enum mrb_vtype tt:8;\
  unsigned int color:3;\
  unsigned int flags:21;\
  struct RClass *c;\
  struct RBasic *gcnext

struct RBasic {
  MRB_OBJECT_HEADER;
};

struct RObject {
  MRB_OBJECT_HEADER;
  struct iv_tbl *iv;
};

class.h

struct RClass {
  MRB_OBJECT_HEADER;
  struct iv_tbl *iv;
  struct kh_mt *mt;
  struct RClass *super;
};
iv_table
instance variables table