2010-08-23
MacRubyのPointerクラスについて
Cocoa APIを使用していると、引数にポインタ変数を渡さなければいけないときがあります。多くはNSError* error;のような変数が必要になるケースでしょうか。
Rubyにはポインタ変数を扱うことができるクラスが存在しないため、MacRubyではPointerクラスが追加されています。
// ObjC NSError* error; # MacRuby error = Pointer.new('@') error = Pointer.new(:object)
作成したPointerインスタンスの値はerror[0]と参照することができます。Cocoa APIにもCocoa APIにはerrorをそのまま渡せばMacRubyが良きに計らってくれるみたい。参考:Probing Cocoa With MacRubyerror[0]を渡します。
Probing Cocoa With MacRubyに書かれていますが、以下のようにPointerを使います。
$ macirb
irb(main):001:0> framework 'Cocoa'
=> true
irb(main):002:0> err = Pointer.new(:object)
=> #<Pointer:0x200c3ac80>
irb(main):003:0> string = NSString.stringWithContentsOfFile('/', encoding: NSUTF8StringEncoding, error: err)
=> nil
irb(main):004:0> puts err[0].description
Error Domain=NSCocoaErrorDomain Code=257 UserInfo=0x200c16b80 "The file “Mac OS X” couldn’t be opened because you don’t have permission to view it." Underlying Error=(Error Domain=NSPOSIXErrorDomain Code=13 "The operation couldn’t be completed. Permission denied")
=> nil
char* name[5];のようなインスタンスを作成するには、
name = Pointer.new('c', 5) name[0] = 'a' name[1] = 'b' name[2] = 'c' name[3] = 'd' name[4] = 'e'
と、Pointer.newの第2引数にサイズを指定します。
以下の構造体 Type の調べ方を追記
Cocoaで用意されている構造体のTypeは
irb(main):015:0> NSRect.type
=> "{CGRect={CGPoint=dd}{CGSize=dd}}"
と調べることができます。NSRect *rect[2];のような変数は
rect = Pointer.new("{CGRect={CGPoint=dd}{CGSize=dd}}", 2) # または rect = Pointer.new(NSRect.type, 2)
と作ることができます。
おまけ。fieldsメソッドを使うと、構造体のメンバ一覧を取得することができるようです。
irb(main):019:0> NSRect.fields => [:origin, :size]
参考 : Objective-CコードからCの構造体を簡単ログ出力(with MacRuby) - kyabの日記
MacRuby: The Definitive Guideの説明もあわせてご覧ください。
Pointerクラスのメソッド
- Pointer.new(Type [, size])
- Pointer.new_with_type(Type [, size])
- Pointerインスタンスを作成します。Typeに指定する値は、Type Encodingsを参考にしてください。
- Pointer.magic_cookie(Integer)
- OpenGL に関するチケット #1112 によって追加されました。void *を受け付ける引数に対して、(void *)にキャストした即値を渡さないといけないようなケースで使うみたい。MacRuby 0.9から使えます。
- Pointer#type
- Typeを確認する際に使用します。
error = Pointer.new(:object) p error.type # => "@"
- Pointer#cast!(Type)
- Typeを変更する際に使用します。JavaScriptを動かすときに使っているので、それを参考にしてもらえると良いかと。
- Pointer#[nth]=value
- nth 番目にvalueを設定します。
- Pointer#assign(value)
- ごめんなさい。どのように使うのかわかりません。コメントで使い方を教えてもらったので、そちらを参照してください。
- Pointer#+ offset
- Pointer#- offset
- 指定したoffsetからのPointerインスタンスを返します。
- メソッドが追加されました。MacRuby 0.8から使えます。
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
トラックバック - http://d.hatena.ne.jp/Watson/20100823/1282543331
