About pointer (ポインタについて) (EXPERIMENTAL FEATURE)

非常に限定的ながらポインタを扱うことが出来るようになりました (0.2.5 にて追加)。

構造体を作成する時に、ポインタとしたい要素を配列としてくくることで定義できます。

C と ruby を並べて記述しています (左側が ruby、右側が C):

int [:a]        # => int *a

int [[[[:a]]]]  # => int ****a

int [:a, 4]     # =>     (NOW) int (*a)[4]
                #    (FEATURE) int *a[4]      : "a" is a 4 elements pointer of int

int [:a], 4     # =>     (NOW) int *a[4]
                #    (FEATURE) int (*a)[4]    : "a" is a pointer of 4 elements int

int [:a, 4], 8  # =>     (NOW) int (*a[8])[4]
                #    (FEATURE) int (*a[4])[8] : "a" is a 4 elements pointer of 8 elements int

const int [:a]  # =>     (NOW) int *const a
                #    (FEATURE) const int *a   : "a" is a pointer of constant int

int [const(:a)] # =>     (NOW) NOT WORK
                #    (FEATURE) int *const a   : "a" is a constant pointer of int

a[]             # => *a , a[0]
a[1]            # => a[1]
a[][1]          # => (*a)[1] , a[0][1]

実際に利用した例 (ruby の規律から逸脱しているため、実用しないで下さい):

X = Gogyou.struct {
  int [:a]
}

frozen_str = "abcdefghijklmn"
x = X.new([frozen_str].pack("p"))
frozen_str.freeze

x.a[] = 0x44434241      # *x.a = 0x44434241
p frozen_str            # => "ABCDefghijklmn"
                        #     ^^^^

x.a[2] ^= 0x20202020    # same as C code
p frozen_str            # => "ABCDefghIJKLmn"
                        #             ^^^^

x.a += 1                # address + sizeof(int[1])
x.a[] = 0x24232221      # *x.a = 0x24232221
p frozen_str            # => "ABCD!\"\#$IJKLmn"
                        #         ^^^^^^

実験的な機能のため、以下の制限(出来無いこと)があります:

自己参照構造体、相互参照構造体について

ポインタによる自己参照構造体、相互参照構造体を定義する場合、Gogyou::Struct クラスを継承したクラスを定義することで可能です。

struct TypeA;

struct TypeB
{
    struct TypeA *a;
    struct TypeB *b;
};

struct TypeA
{
    struct TypeB *b;
};
class TypeA < Gogyou::Struct
  # class definition only!
end

class TypeB < Gogyou::Struct
  struct {
    struct TypeA, [:a]
    struct TypeB, [:b]
  }
end

class TypeA
  struct {
    struct TypeB, [:b]
  }
end