MacRuby DoJo (道場)

Pointer クラス

Cocoa API を使用していると、引数にポインタ変数を渡さなければいけないときがあります。多くは NSError* error; のような変数が必要になるケースでしょうか。Ruby にはポインタ変数を扱うことができるクラスが存在しないため、MacRuby では Pointer クラスが追加されています。

Pointer クラスを使用して、Objective-C の NSError* error; と等しい変数を用意するには以下のような記述になります。

1
error = Pointer.new('@')

Pointer.new の引数の @ は、「オブジェクトのポインタ変数をつくりなさい」と指示しています。@ のほかにも種類があり Type Encodings で確認することができます。

Pointer クラスについて、もう少し詳しい例を下に示します。

1
2
3
4
5
6
7
8
9
10
11
framework 'Cocoa'

error = Pointer.new('@')
url = NSURL.URLWithString("http://your_url")
string = NSString.stringWithContentsOfURL(url, encoding: NSUTF8StringEncoding, error: error)

if error[0]
  puts error[0].description
  raise
end
puts string

NSString.stringWithContentsOfURL でエラーが発生すると、error[0] にエラー内容が格納されます。

char* name[5]; のようなインスタンスを作成するには、以下のように Pointer.new の第 2 引数でサイズを指定します。

1
2
3
4
5
6
name = Pointer.new('c', 5)
name[0] = 'a'
name[1] = 'b'
name[2] = 'c'
name[3] = 'd'
name[4] = 'e'

NSRect *rect[2]; のような構造体のポインタ変数のインスタンスは、以下のように作成できます。

1
rect = Pointer.new("{CGRect={CGPoint=dd}{CGSize=dd}}", 2)

構造体の内容を正確に把握しなければ、変数を用意することができません。 そこで、NSRect.type と構造体に対して type メソッドを実行すると "{CGRect={CGPoint=dd}{CGSize=dd}}" と構造体の Type を取得することができるようになっています。上の例は以下のように書くことができます。

1
rect = Pointer.new(NSRect.type, 2)

ポインタ種類の別名

@ ではどのようなポインタとなるのかわかりにくいため、MacRuby では Pointer.new('@') を以下のように書くこともできます。

1
error = Pointer.new(:object)

以下の表のように別名が用意されています。

内容ポインタ別名
charPointer.new(‘c’)Pointer.new(:char)
unsigned charPointer.new(‘C’)Pointer.new(:uchar)
shortPointer.new(’s’)Pointer.new(:short)
unsigned shortPointer.new(‘S’)Pointer.new(:ushort)
intPointer.new(‘i’)Pointer.new(:int)
unsigned intPointer.new(‘I’)Pointer.new(:uint)
longPointer.new(‘l’)Pointer.new(:long)
unsigned longPointer.new(‘L’)Pointer.new(:ulong)
long longPointer.new(‘q’)Pointer.new(:long_long)
unsigned long longPointer.new(‘Q’)Pointer.new(:ulong_long)
floatPointer.new(‘f’)Pointer.new(:float)
doublePointer.new(‘d’)Pointer.new(:double)
character string (char *)Pointer.new(‘*’)Pointer.new(:string)
pointerPointer.new(‘^’)Pointer.new(:pointer)
objectPointer.new(‘@’)Pointer.new(:object)
Pointer.new(:id)
class object (Class)Pointer.new(‘#’)Pointer.new(:class)
booleanPointer.new(‘B’)Pointer.new(:boolean)
Pointer.new(:bool)
method selector (SEL)Pointer.new(‘:’)Pointer.new(:selector)
Pointer.new(:sel)

Pointer クラスのメソッド

Pointer.new

Pointer クラスのインスタンスを作成して返します。

  • new(type, size = 1) -> Pointer
    • [PARAM] type:
      • どのようなポインタ変数を作成するか指定します。
    • [PARAM] size:
      • ポインタ変数のサイズを指定します。
    • [RETURN]
      • 作成した Pointer のインスタンスを返します。

Pointer.new_with_type

Pointer.new の別名です。

Pointer.magic_cookie

即値を (void *) へキャストした Pointer のインスタンスを返します。

  • magic_cookie(val) -> Pointer
    • [PARAM] val:
      • 数値を指定します。
    • [RETURN]
      • (void *) に即値をキャストした Pointer のインスタンスを返します。

OpenGL に関するチケット #1112 でこのメソッドが追加されました。

Pointer#type

どのような種類のポインタか確認するのに使用します。

  • type -> String
    • [RETURN]
      • ポインタの種類を返します。
1
2
3
4
>> framework 'Cocoa'
>> pointer = Pointer.new(NSRect.type)
>> pointer.type
=> "{CGRect={CGPoint=dd}{CGSize=dd}}"

Pointer#cast!

ポインタの種類を変更します。

  • cast!(type) -> self
    • [PARAM] type:
      • 変更先のポインタの種類を指定します。
    • [RETURN]
      • ポインタの種類を変更したオブジェクトを返します。
1
2
3
4
5
6
>> pointer = Pointer.new('i')
>> pointer.type
=> "i"
>> pointer.cast!('I')
>> pointer.type
=> "I"

Pointer#[]

nth 番目の内容を取得します。

  • self[nth]
    • [PARAM] nth:
      • 取得する内容の位置を指定します。
    • [RETURN]
      • nth 番目の内容を返します。

Pointer#[]=

nth 番目の内容を val で置き換えます。

  • self[nth] = val
    • [PARAM] nth:
      • 置き換える内容の位置を指定します。
    • [PARAM] val:
      • 置き換える内容を指定します。
    • [RETURN]
      • val を返します。

Pointer#value

0 番目の内容を取得します。

  • value
    • [RETURN]
      • 0 番目の内容を取得します。
1
2
3
4
5
pointer = Pointer.new('c')
pointer[0] = 42

pointer[0]    # => 42
pointer.value # => 42

Pointer#assign

0 番目の内容を val で置き換えます。

  • assign(val)
    • [PARAM] val:
      • 置き換える内容を指定します。
    • [RETURN]
      • val を返します。

Pointer#+

指定した offset からの Pointer インスタンスを返します。

  • self + offset -> Pointer
    • [PARAM] offset:
      • 取得する内容の位置を指定します。
    • [RETURN]
      • 指定した位置からの Pointer インスタンスを返します。
1
2
3
4
5
6
7
8
9
10
11
name = Pointer.new('c', 5)
name[0] = 10
name[1] = 11
name[2] = 12
name[3] = 13
name[4] = 14

tmp = name + 3
2.times do |i|
  p tmp[i] # => 13, 14
end

Pointer#-

Pointer#+ と同じように、指定した offset からの Pointer インスタンスを返します。

  • self - offset -> Pointer
    • [PARAM] offset:
      • 取得する内容の位置を指定します。
    • [RETURN]
      • 指定した位置からの Pointer インスタンスを返します。

Pointer#to_object

TBD

Comments