ぼんやりと考えている人

ひろしまなおき (廣島直己)
名前: ひろしまなおき (廣島直己)
住処: シリコンバレー
職業: しがないプログラマ
家族: 愛妻一人、息子一人、娘一人
道具: ハーレー二台、ギター三本
電紙: n at h7a.org

Twitter

« November 2017
S M T W T F S
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30    

以前にぼんやりと考えたこと

最近のコメント

  • ひろしま (ひらがなせいかつ …): じゅくじくんは なくした ほうが いい ですね。ぼくは…
  • たんぽぽ (ひらがなせいかつ …): きゅうに ぜんぶの ことばを ひらがなだけに する…
  • とね まさひこ… (ひらがなせいかつ …): ぼくは ものかき だが, かんじが きらいなので,…
  • とりえ (ひらがなせいかつ …): このさいとは みているだけで なんとなく ほんわか…
  • ひろしま (思い通りの日本語…): こうどな ほんを よめなければ、こうどな たんごを 学…
  • nt4 (思い通りの日本語…): ひらがなせいかつに初めて接し、興味を覚えました。そ…
  • ひろしま (ひらがなせいかつ …): やはり、がいこくに くらしていたり、がいこくとの か…
  • ぷりうりうぷ… (ひらがなせいかつ …): こんにちは。すうぇーでんに すんでいます。いとうさ…
  • Joi Ito (ひらがなせいかつ …): もと べいにち たいしの Edwin O. Reischauer さん…
  • yonay (理屈じゃないとい…): なんか、著者の主張を誤解しているような気がするよ。…

  • Powered by Pivot - 1.40.5: 'Dreadwind'
  • SPAM Poison
  • XMLフィード(RSS 1.0)
  • Atomフィード

08 November '2007 - 12:26 | 技術動向 Text Input Source Services を RubyCocoa で使う

Psychs 先生が、Text Input Source Services なるものが 「Leopard で追加されたらしい」とさえずっていたので、つい出来心で遊んでみることにした。Leopard で遊ぶということは、RubyCocoa で遊ぶということなので、さくっと ruby で書いてみる。

と思いきや、このモジュール、なんと Carbon だと。もう、いいよ、Carbon は。

で、とりあえず TextInputSources.Private.bridgesupport を手作業で(笑)でっちあげて、いくつか関数を実行して遊んでみた。当然ながら期待どおりにさくっと動いた。前にやった IOKit とかと違ってぜんぜんパラメータもないし、呼ぶだけ系なので楽勝。

たとえば、入力を US (というか ASCII だけれど) に変更するスクリプトは、こんな感じで書ける。 

require 'osx/cocoa'
OSX.load_bridge_support_file 'TextInputSources.Private.bridgesupport'
OSX::TISSelectInputSource OSX::TISCopyCurrentASCIICapableKeyboardInputSource()

最初の二行はおまじないなので、じっしつ一行だけ。

たとえば、Terminal とか QuickSilver とか、特定のアプリがフォーカスを得た時にこのスクリプトを呼ぶようにしておけば便利。と思いきや、どうやればそうできるのかが分からない。Psychs 先生に聞いてみたら、どうやら OSX ではすべてのウィンドウのイベントをフックするとか、Windows みたいに簡単にはできないらしい。うーむ。

まあ、それはそれとして、たとえば TISGetInputSourceProperty() を使って、

p OSX::TISGetInputSourceProperty(OSX::TISCopyCurrentKeyboardInputSource(), OSX::KTISPropertyInputSourceLanguages)

みたいなことをやると、たとえば

#<OSX::ObjcPtr:0xd6a24 cptr=0x3b6280 allocated_size=0 encoding=v>

みたいに表示されて、ちゃんと void* なポインタが取れてるのは分かる。なぜか allocated_size はゼロって書いてあるけど、たぶんサイズが分からないからゼロってことにしてあるだけだと思うので気にしない。実際、データは入ってて、読むことはできる。

で、この void* なポインタはキャストして使わないといけない。上の例だと、この void* なポインタは「文字列へのポインタ(CFStringRefs)の配列へのポインタ (CFArrayRef)」にキャストして使う。のだけれど、どうやってキャストするのかが分からない。って、さすがにそれは無理か。

結局、こんな Carbon あがりの半端者をむりやり RubyCocoa で使えるようにしたって、たいして嬉しくならなかったりするらしい。

ちなみに、void* なポインタを、指定されたオブジェクトだと盲目的に信じて無理矢理オブジェクトを生成して返す関数でも作ってみたらどうだろうか。とうぜん、ruby コードなのに SEGV だらけになるんだろうな。

いったい、なんのための ruby かと。冒涜するのもいい加減にしろと。

Trackback link:

トラックバック用URLを生成するには、JavaScriptを有効にしてください。


試しに、bridgesupport の TISGetInputSourceProperty で
<retval declared_type='void*' type='^v'/>
となっているところを
<retval declared_type='id' type='@'/>
と変えてみると問題なく動作しました。
ご存じかも知れませんが、少し補足しておきます。
これで動くのは
CoreFoundation の CFStringRef と CFArrayRef が
Cocoa の NSString* と NSArray* (つまりid) と互換だからです。
たとえば、ポインタの指示先は C の struct __CFString としても、
Objective-C の NSString としても扱えるように設計されています。
ありがとうございます。やっぱ、id でいいんですね。

じつはこのエントリを書いたあとにいろいろ試していて、id にすれば動くということを発見していたのだけれど、CFStringRef と CFArrayRef 以外の時にも動く理由がよく分からなくて混乱していました。この二つは先生が書いてくれた理由をどっかで読んでたので問題なかったのですが、なんで CFBooleanRef と CFDataRef の時にもちゃんと動くんだろうか?と。

でも、たぶん、こいつらもぜんぶ id 互換ってことでいいんでしょうね。

ただ、id に変更していろいろ試していたら、ひどいバグをみつけて困ってしまっていました。

ぼくの環境では US キーボードで、OSX::KTISPropertyIconRef を取ろうとすると、なんと (void*)1 が帰ってきます orz

なので、id にしていると必ず SEGV を起こせてしまいます。0 じゃなくて 1 ってあたりがいかにもバグっぽいので libffi でも深追いしてみようかと思ったのですが、どこが間違ってるのかよく分からないので、とりあえず talk にでも書いておいた方がいいですかね。
互換オブジェクトのリストは、
http://developer.apple.com/documentation..
に載っています。
CFBooleanRef については、RubyCocoa で NSCFBoolean に変換するので '@' で問題ないはずです。

ただ、IconRef とかは、どこかで NSImage#initWithIconRef で NSImage にする必要がありますが。

とりあえず、ObjcPtr#as_id を trunk に追加しておいたので、'^v' のまま as_id すると NSObject として取り出せるようになりました。名前がいまいちなのと、もうちょっと何とかならないかと思うので、まだ今後変える可能性があります。

うちでは、OSX::KTISPropertyIconRef はかならず 0 を返してくるみたいです。1 が返ってくるのはおかしいですね。PPC っていうことはないですよね? (PPC は結構あやしい)

もしよかったらレポートしておいていただけると助かります。
おぉ、そんなリストが。いやー、勉強になるなあ。ありがとうございます。

ObjcPtr#as_id は便利でいいですね。これなら戻り値が (void*)1 だったら回避するというヒドス kludge を入れることができますしねw しかし、メソッド追加して解決するというのはぜんぜん気づきませんでした。さすが、コミッタは偉い :)

ちなみに、レポートしると言われたのでしておこうかと思ったのですが、よく考えてみると先生の環境で再現しないというのはちょっとおかしい。なので、念のために同じことをするコードを C で書いて実験してみたら、なんと (void*)1 が帰って来てましたよw

つまり、RubyCocoa はシロってことでした。うーむ。

ぼくの環境だけがおかしいのかも知れないので、他の Leopard で追試して、再現するようなら Apple にレポートしておきますw

ちなみに、PPC って何でしょうか?ぼくは、使えない OSX になんか見向きもしなかった真の勝利者たる誉れ高き 2006 Switcher ですが、それが何か?
なんと、C レベルでも 1 でしたか。。

この件について、Laurent と話してみたんですが、TextInputSource.bridgesupport を OS に添付するように Apple にレポートしといてよ、と言われました。もしよかったら、お願いできますか?

ぼくも 2006 Switcher なので、PPC についてはよく知りませんw
ごめんなさい。
さっそくですが、ObjcPtr#cast_as(encoding) に変更になりました。
ptr.cast_as('@') で as_id 相当の動作になります。
さっそく Apple にレポートしておきました。

で、メソッド名は #cast_as() ですか。いいですねぇ、ruby なのにw
# as_id よりも to_id の方がいいんじゃないかと思ってたのだけれど、何にでもできる方がいい :)

ちなみに、(void*)1 問題は、他の環境でも再現できるかどうか、他の人にも試してもらおうと思ったら、OSX.load_bridge_support_file が undefined とか言われて動かないと言われました。もしかしてこれって、Leopard の RubyCocoa には入ってないメソッドなんですかね。ぼくも同じのを使ってるつもりだったのだけれど、いろいろやってるのでよく分からない。

ぼくの環境では何度やっても、入力が US の時だけ (void*)1 で、それ以外の時は NULL が返ってくるので、ぜひ誰かにも再現してもらいたいなあ。再現されたらレポートするので、誰か再現して下さいw

  
情報を記憶する

Emoticons /

酢ハムがいったいどんなハムなのかはともかく…
 

 

通知:
非公開:

注意: 使用できるタグは <b> と <i> のみです。URLやメールアドレスはそのまま記述すればリンクになります。