2007年 01月 03日

ruby clr, UI 作りに VS.Net のフォームデザイナつかう


できた!(表示させるところまで)
ハマったのはプロジェクトを適当に WindowsApplication1 とかにしていたため、namespace がそれに設定されて、ActiveSupport から uninitialized constant がでたらへん。全部 UserInterface とかって書き換えたらいけた。

さてあとはイベントハンドラの設定方法か。。


あと本筋とは関係ないけど

  • gems で rubyclr を入れてたけど、winforms を見つけてくれないので本家からダウンロードして RUBYLIB 設定するようにした。
  • でもどっちにしろ gems は必要 (AS に依存してる) なんだよね
  • っていうか起動おそいよ><


メモ

  • プロジェクトのプロパティで、出力の形式(デフォルトは Windows アプリケーション) をクラスライブラリにすれば dll になって単体で実行できなくなる
  • でも UI のチェックがしにくくなるから exe のほうがいい気がする

rubyclr フォームの要素にアクセス

デフォルトだと、フォームにおいたやつはそのフォームの private メンバになってしまうようなので、MainForm.Designer.cs を開いて一番したにあるやつを全部 public にしないといけない。

rubyclr スレッド

もしかして ruby のスレッド使えない疑惑
あーいっかい run に入るとスレッドスイッチおこらない。だめだ。ここでゲームオーバー。drb 使えないんじゃ意味がない。

ふと思いついて、Timer を配置して

# threadTimer という名前で配置。Interval は 10 で、最初から Enable を true にしてある。
form.threadTimer.Tick do |sender, arg|
    Thread.pass
end

したらスイッチした。いけるかも。単純なコードしか試してないけど……

あー。謎のエラーで終了することがある。無理かも……

TextBox が溢れてエラーになってただけっぽい。よくわからないけど、標準出力に出すようにしたら大丈夫になった。(時間を永遠表示させてる)

TextBox#Text= の処理の間にスレッドの割り込みが入ってまた TextBox#Text= が呼び出されると、もとのコンテキストに戻ったときにエラーになるのかな。そんな感じがするけどよくわからない

ちがうなぁ。p @form.chkHogehoge って参照しただけでも落ちる。何が悪いんだろう。回避方法あるのかなぁ。スレッド使うのは難しいようだ

rubyclr Timer でスレッドスイッチの問題

エラーでまくり (フォーム内の要素を参照した時点で落ちる)でだめなので原因を考える

  • Ruby インタプリタがびっくりすること
    • Ruby インタプリタだけの場合、スレッドをスイッチするのは Ruby インタプリタだけだけど、この場合 Timer による強制スイッチが入る
  • CLR 側がびっくりすること
    • Ruby インタプリタがスレッドスイッチでごっそりメモリいぢくること?

再現性100%の問題なので、タイミングがどうとかいう話ではない気がする。タイマーの Interval を変えてみても発生するので Ruby インタプリタがビックリしてるわけじゃなさそう。そもそも Ruby の例外は上がらない。

スレッドスイッチさせなければ普通に参照できるため、どっかでそのへんの何かが壊れてる予感。うーん

とりあえず、Ruby からスイッチ (pass) されたスレッド内でフォーム要素を参照しなければ落ちないみたいだ。つまり、本当のフォームの要素とは別に、状態設定用のインスタンス変数を作っておいて、実際のフォーム要素への反映はタイマーから起動されるクロージャ内でやれば大丈夫。
遠回りだけど(そしてこの回避方法で全てがうまくいくかわからない)

自動リロード GUI / Windows 版

http://lab.lowreal.net/trac/changeset/557
とりあえず動いたのでチェックイン

  • メニューのイベント割り当ててない
  • exe 化したい
  • この際多少マジカル☆なのは気にしない

AS と exerb

なんかうまく exe 化できない。AS の core_ext の require あたりがどうもダメみたいだ。core_ext は動的に require の文字列つくってやってるけど、これがだめなのかなぁ。
no such file って言われてしまう。

path に AS の lib ディレクトリを追加して、内部ファイル名のプリフィックス削除した
あとたぶんそれを読み込んでるファイルの書き換えもしないといけない。

gems とすんごい相性悪い。。。
rubygems.rb を偽装して自力で依存解決したファイルつくってエラーでないところまでやった、と思いきやセグフォって (ここは rubyclr) 泣きたい

なんか

無理に単体 exe 化するより rubyw.exe とか全部詰め込んだ方が楽な気がした。あるいは ASR をランタイムとしてインストールしてもらうとか。

Windows が RingServer になれない

てきとうに試してて気付いたけど、うちの環境だとなぜか Windows だけ RingServer になれない。直接 new_with_uri すればちゃんと接続できるけど、UDP 送って発見できないようだ。なんでだろう。

Windows 上の RingServer が見つからないのは rubyclr から起動した時だけっぽい。シンプルなやつは普通に発見できる。そもそもローカルからさえ見つけられない。

exe 化できない

rubyclr/core.rb でセグフォる。うーん。
依存ファイル全部もってきて、隔離した環境(になってるかわからないけど)にして実行すると

ハンドルされていない例外: System.IO.FileLoadException: ファイルまたはアセンブリ
'Runtime, Version=0.1.0.0, Culture=neutral, PublicKeyToken=null'、またはその依存
関係の 1 つが読み込めませんでした。要求された最小限のアクセス許可を与えることが
できませんでした。 (HRESULT からの例外: 0x80131417)
ファイル名 'Runtime, Version=0.1.0.0, Culture=neutral, PublicKeyToken=null' です
。 ---> System.Security.Policy.PolicyException: 必要なアクセス許可を取得できませ
ん。
場所 System.Security.SecurityManager.ResolvePolicy(Evidence evidence, Permiss
ionSet reqdPset, PermissionSet optPset, PermissionSet denyPset, PermissionSet& d
enied, Boolean checkExecutionPermission)
場所 System.Security.SecurityManager.ResolvePolicy(Evidence evidence, Permiss
ionSet reqdPset, PermissionSet optPset, PermissionSet denyPset, PermissionSet& d
enied, Int32& securitySpecialFlags, Boolean checkExecutionPermission)

とかいわれる。信頼できないコードになってる? 同じファイルなんだけどなぁ。Ruby みたいにディレクトリさかのぼって書き込み権限見てるとかそういうのなんかなぁ。

このエラーはセグフォとは無関係。ディレクトリ変えたら動いた。ネットワークドライブ上では実行できない?ようだ

諦めよう

いい方法思いつくまで保留

rubyclr

ruby 側でハンドルするまでもない処理 (this.Close(); だけとか)を C# で書いちゃえるのは素晴らしいなぁ。

.net のセキュリティ機構

やばい意味わからない。
例えば

System.Diagnostics.Process.Start('http://lowreal.net/'); 

はセキュリティエラーで例外になってしまう。

あ−

GUI いらないな

ライブラリとインタプリタをまとめただけ

http://lab.lowreal.net/trac/changeset/564
CUI バージョンのほうが罠がなくてよさそうだ……ファイルサイズ小さい (800KB) し(例えば gems とかを含まないからね!)
exerb は今のところアイコンに最大 8bit のものしか指定できない。ので作った後 IconReset とかいうので設定しなおしてみた。