昔の最近の出来事(2004.10)

2004/10/31

AM起床。雷がうるさくてあまり寝れなかった感じ。

Dのマニュアルを眺めていたら、 以前判らなかった参照無しオブジェクトの nullとの比較演算子を発見したり。「===」や「!==」を使えば良い らしい。確かに先日のコードもそれに置きかえれば、期待通りの動作 を行なう様です。でもこれってどうなんですかね?うっかり間違えると Segfaultするというのには問題ありな気が。過去、C言語でif文の中に 代入式「=」を書けるのが問題になってたりする様にも思いますが、 それと同じような間違いを起こしそうな気がします。まぁ、Segfaultで 死んでくれた方が、問題個所の特定は簡単なのでまだマシかも知れませんが。
それにしても、if文の中にオブジェクトをそのままつっこんで、うまく「===」と同等の 比較演算が選択されて実際に期待通りの動作を行なう事を考えると、 「===」のような特別な比較演算子を用意する理由が特に無いような 気がしますが.....

Dプログラミング。行列クラスやクォータニオンクラスを作ってみたり。 取りあえず動いていそうな予感。

ペットボトルを潰しながらファミ通WaveDVDを見たり。ネタ的に少し枯れている 感じもありますが、ゲームショーで発表されたゲームの画面とか色々。 Ysが何故かKONAMIで発売というのに「お?なんで?」とか思ったり。他、 「今はまだまだ...」と今まで触れずにいた「ランブルローズ」。かなりイイ感じに はっちゃけ始めているのにグっときたり。このまま少しやり過ぎなくらいに 行ってくれると買ってしまうかも。意外とオンライン(を全面に推した)ゲームが 少ない様にも思ったのですが、実はそうでもないのかしら? 他、やり込みKINGのセレクション、レベル3のプリンでポケモンリーグ制覇 ってやつ。ポケモンは一度もやった事無いのですが、170回近くリセットを 繰り返して、普通、そこまでやってダメなものはダメだと諦めてしまうような 気がするのですが、それでもいけると思い、実際にいける所がスゲーと思ったり。

表紙絵を変えてみたり。薄塗りの水彩っぽいノリで引きずりをうまく使える のかと思ったのですが、透明領域の白が混ざってきて、何か思っているのと ちょっと違うという感じで、うまくコントロールができずじまい。

新型PS2のTVCM。DVDのパッケージとの比が本当にあれだとすると、本当に小さい 気が。てゆーか、あんな小さくできるんだという驚きの方が大きかったかも。 あと一回モデルチェンジやれば、次はPS-ONE並になったりするのかしら?と 思わせるように感じました。

2004/10/30

昼頃起床。寒くて危うく風邪ひきそうになってみたり。

何気にCygwinパッケージアップデートを行なっていたら、glib-2.xやGTK+-2.x ライブラリがアップデートされてました。でも、何故かGIMPのconfigureでは glibのバージョン判定に引っかかって、configureが通りません。 そんな訳で、少しパッケージ一覧を眺めてみたところ、開発用のヘッダが ダウンロードされていない事が判明してみたり(^^;そんな感じで 入れてみた所、印刷機能をdisableにする必要がありましたが一応 通りました。でも、makeを実行するとtoolディレクトリのmakeで いきなりエラー。そこを外してmakeしていると、途中ライブラリの makeでエラー。むーん。

Dプログラミング。単体テスト機能というものが備わっているらしいので、 それを使って三次元ベクトルクラスの確認ができないかと考えてみたり。 文法上は、クラスの中にある決まったメソッド名であるunittest()を 定義して、その中にテストケースを書いてやれば良いらしい。 ところが、そのテストケースを実際に実行する方法がよく判らなかったり。 ドキュメントによれば、main()関数を実行する前に全クラスの unittest()メソッドを実行すると書かれているのですが、 どうやってもそのコードを通りませんでした。gdcだからかどうかは 判りませんが、謎。
ところで、この単体テスト機能についてなのですが、TANEが思っていたのと 少し感じが違いました。Dのポリシーとしては、テストバージョンでは 毎回テストルーチンを通して、モジュールが壊れていない事を毎回テスト する事で、全体テスト前に部分破壊を検出するという事のようです。 TANEが思っていたのは、各クラスを単体でテストする為の機構だと思っていた ので、例えば、main()関数が無い場合は適当なスタブがリンクされて、 unittestメソッドが実行されるという感じ。gdcを使ったという理由が あるのかも知れませんが、main()関数が無いとリンク時にエラーになります し、先にも述べたようにunittestメソッドが実行されないので、 実際にはTANEが思っているような動作を行なうのかも知れませんが。 ところで、Javaの場合だと、JavaVM実行時にクラスファイルを指定して、 指定されたクラスのmain()メソッドから実行が開始されます。 これを使えば、下請けクラスのテストを全てmain()メソッド内に入れる という方法が使えるかも知れません。ただし、Dのunittestメソッドは コンパイルオプションで完全に実行モジュールから抜く事ができる ようですが、Javaのmain()メソッドを使った方法だとそういう事は できません。Javaでも実はうまい方法があるのかも知れませんが。

三次元ベクトルクラスを書いていて、一つ疑問が湧いて来たり。 例えば、aとbの二つのオブジェクトを宣言したとして、 a=bみたいな事をした後、オブジェクトbのメンバーフィールドを 更新すると、aの方からもその更新が見えてしまいます。これは 参照型なので仕方ありませんが、頂点データのようなものは、 プリミティブ型の様に扱いたいものです。ところが、 c=a+b のようなことを表現したいとき、演算子を オーバーロードするかどうかに関わらず、元になるインスタンスa,bを 壊さない様に、演算後の結果をcから参照できるようにするには、

  Vec3D opAdd( Vec3D b ){ /* add */
    return( new Vec3D( this.x+b.x , this.y+b.y , this.z+b.z ) ) ;
  }

という感じに、毎回新たな領域を取り、そこに結果を格納して返す 必要がある様に思います。 でも、こうしてしまうと、イマイチ性能的に難があるといいますか。 例えば、頂点座標変換を行なうような場合、演算子を前述のような 方法でオーバーロードすると、dst=src+(dist*scale)の様に 数種類の演算を行なうと、演算子の出現回数分newが実行される 事になると思います。頂点の座標変換のような事をする場合、 大抵の場合元の頂点数と座標変換後の頂点数は同じ数である事が保証されて います。C言語で書く場合だと、頂点数と同じサイズの結果格納バッファを 設けて、バッファに対して変換過程の演算値を保持したり、変換後データを 入れるなりすれば良いと思います。演算過程にしても、マクロなり関数の インライン展開を使うなど、普通にやれば演算過程でメモリ割り 当てを必要とする事はありません(というか本来メモリアクセスができるだけ 発生しないよう最適化を行なうのがコンパイラの役割なのですから当然です)。 もっと良い方法があるのかも知れませんが、思いつかず。こういうミクロな 演算を行なうメソッドを用意しない方が良いのかしら。

もう少し考えてみました。一番最初にsetterを使用して、その後の 演算は全て代入演算で行なうという感じ。

/*c=a+b ;*/
c.set(a) ; /* aのメンバー変数値をcのメンバー変数にコピーする */
c.add(b) ; /* cのメンバー変数値にbのメンバー変数値を加える   */

既に存在する結果格納領域を再利用できるという点では、こちらの方がよさげ (メソッドをインライン展開ができるならば、特別に考える事なく最適化前の 元の式を構築できるでしょう)なのですが、全く直感的でなくなるのが難点です (LISPで演算式を書くような感じです(^^;)。 問題は、演算子のオーバーロード方式で書いた後に性能が気になった所で、 前述のsetter+自己更新方式にしたとしても、変更量が多過ぎて書き換え 不能な気がします。 やはり、ミクロな演算を行なうメソッドを用意するのではなく、 性能を落とさない点を見切ったマクロな演算(変換と呼んだ方が良いかも) を行なうメソッドを用意するべきなのかも知れません。

一応性能比較をしてみました。念のため、二度実行しています。 やはり、演算子毎にnewを実行するのと自己更新とでは、 100倍くらい前者の方が遅いようです。

% cat performtest.d
import std.math;
import std.c.time;

class Vec3D {
  double x ;
  double y ;
  double z ;

  this (double x, double y, double z ){
    this.x=x ;
    this.y=y ;
    this.z=z ;
  }

  Vec3D opAdd( Vec3D b ){
    return( new Vec3D( this.x+b.x , this.y+b.y , this.z+b.z ) ) ;
  }

  void add( Vec3D b ){
    this.x+=b.x ;
    this.y+=b.y ;
    this.z+=b.z ;
    return ;
  }
}

int main(){
  Vec3D a = new Vec3D(0.0,0.0,0.0) ;
  Vec3D b = new Vec3D(0.0,0.0,0.0) ;
  Vec3D c = new Vec3D(1.0,1.0,1.0) ;
  int i ;
  time_t curtime ;

  time(&curtime) ; printf("%s",ctime(&curtime)) ;
  for( i=0 ; i<65535*256 ; i++ ){
    a.add(c) ;
  }
  time(&curtime) ; printf("%s",ctime(&curtime)) ;
  for( i=0 ; i<65535*256 ; i++ ){
    b=b+c ;
  }
  time(&curtime) ; printf("%s",ctime(&curtime)) ;
  
  return(0) ;
}
% gdc -O3 performtest.d
% ./a.exe 
Sat Oct 30 23:30:40 2004
Sat Oct 30 23:30:41 2004
Sat Oct 30 23:32:22 2004
% ./a.exe 
Sat Oct 30 23:32:31 2004
Sat Oct 30 23:32:32 2004
Sat Oct 30 23:34:12 2004

インライン展開して、ものすごく考えれば、インスタンスを毎回変更する opAdd()メソッド("+"演算子のオーバーロードです)も、 add()メソッドと同じように最適化できそうな気はしますが、 まぁ、コードで性能改善できるなら、そうするのが現実的なのでしょう。
でもなぁ〜、いくらなんでも100倍も遅いのは書き方の問題のような 気がするなぁ。もっと良い書き方があるのかしら?

2004/10/29

日付け越え前に帰着。

昨日Webを巡回していたらいきなりWindowsがハングってしまったので、 強制電源OFF+再起動した所、640x480の画面モードで立ちあがったり。 解像度を戻す為に再起動したり、アイコン位置を元に戻したりで復活。 現在解像度は1280x960になっているのですが、元に戻すのに1024x768 に一度設定した後、再度起動しなおさないと1280x960のメニューが 出てこなかったのですが、1024x768にしただけでアイコン位置が メチャクチャになって、「画面狭っ!」って感じでした。現在の モードにした時は、 目が疲れるとか色々言っていた様な気がするのですが、 慣れというのは恐ろしいものです。

急速に眠くなって死亡。

2004/10/28

日付け越え前に帰着。

Dでプログラム。三次元のベクトルクラスを作成してみたり。

2004/10/27

日付け越え前に帰着。

WBSで見た超薄型ディスプレイ。ディスプレイと言っても、まだ研究段階の もので、モノクロで動画は出ないものでしたが、厚さが紙、フィルムの ような薄さなのです。しかも、絵を変える時に電気を必要とするのですが、 その後は通電しなくても絵が残ったままになるという、不思議な物質って 感じ。いや、久しぶりに発明品っぽいものを見た気がします。

Dでプログラム。クラスを継承してメソッドをオーバーライドする練習を してみたり。手が滑っている事にしばらく気づかず、書き方が悪いのかと 勘違いしてみたりハマり事はありましたが、Javaと同じ感じで良いらしい。

2004/10/26

日付け越え前に帰着。

先日仕掛けたビルドは完了してたので、そのままmake installしてみたり。 でも、nullと比較するコードを食わせてみた所、やっぱりSegfaultで死ぬ 模様。

で、ぐるぐる探っていると、if式の中にオブジェクトをそのままつっこんで 評価するというものがありました。実際にそれを試してみた所、どうやら 期待する動作を行なう様です。

% cat null_ref.d
import std.stream;

class Test{
  int a ;
}

int main(char[][] args){
    Test testclass ;

    printf("step1\n") ;
    if( !testclass ){
      printf("testclass is null (1)\n") ;
    }

    printf("step2\n") ;
    testclass = new Test ;
    if( testclass ){
        printf("testclass is not null(2)\n") ;
    }
    
    printf("step3\n") ;
    testclass=null ;
    if( !testclass ){
      printf("testclass is null (3)\n") ;
    }

    return 0;
}
% gdc null_ref.d
% ./a.exe 
step1
testclass is null (1)
step2
testclass is not null(2)
step3
testclass is null (3)

でも、個人的にはこの記述って好きじゃないのですよね。 理由は(ifの中の式が)どういう結果なのかいまひとつ判りにくいから です。変数名に自然言語的に意味の通じるような名前を付けている 場合はその限りでもありませんが(例えば if( state_is_busy ).. とか)、 そうでなければ、比較演算を必ず入れる様に書きたい所です。 まぁ、C言語の様に「trueとなる結果の実際の値は実装依存」でない のなら、混乱は少ないかも知れませんが。

ともあれ、そこん所を書き換えたら、Javaで書いたクラスがそのまま 動きました。

2004/10/25

日付け越え。

先日の問題の真意のほどは良くわからず。コードで回避するとすれば、 リストのサイズと現在位置を持ち、リストのプリミティブのnextポインタを 参照する前に現在位置で「先頭、末尾、空」を判定するしかないかなぁと 思ったり。

ぐるぐるしていると、gdcの0.8というのが出ていたり。 何か変わっているかも知れないのでビルドしてみる事に。

でも眠くて死亡。

2004/10/24

昼過ぎ起床。

ちょっこり本屋に。特にめぼしいものは無し。ついでに久々にゲーセンに。 「翼神 GIGAWING GENERATION」が置いてありました。 これまでのGIGAWINGシリーズとは違って縦長画面構成になってました。 解像度が高くなっているのですが、人がやっているのを見た感じ、 どうもPCのゲームを見ているというか、スクロールにガタつきがある様に 見えました。グラフィックも 3Dではあるものの、紙にぺったり貼りついたような絵で、GIGAWING2の時の ような凄い印象はありませんでしたし、全体的にイマイチに感じました。 結局やりませんでしたが、やってみるとまた違った感想があるかも。

Dでプログラム。Javaで遊んだ時に書いたリストをそのまま使える かと持ってきたのですが、不具合にハマってみたり。 一つは不具合というよりは仕様の問題ですが、あるクラスで メンバーフィールドの変数(クラス内で使用できる変数)と、メソッドの 名前が同じだと、Dではエラーになるようです。メソッド呼び出しは 必ず最後に括弧を付けるので、名前が同じでも区別は付くので問題は 無いと思われますが、そういう仕様になっているらしい。 もうひとつは不具合っぽいのですが、オブジェクトに実体を与えずに nullを入れてどこにも参照が無い状態を作っていたのですが、 それをnullと比較して実体のある無しを判断した所、nullとの比較で Segfaultするようです。

% cat null_ref.d 
import std.stream;

class Test{
  int a ;
}

int main(char[][] args){
    Test testclass ;

    printf("step1\n") ;

    testclass=null ;

    printf("step2\n") ;

    if( testclass==null ){
        printf("testclass is null\n") ;
    }

    printf("step3\n") ;

    return 0;
}
% gdc null_ref.d 
% ./a.exe 
step1
step2
Segmentation fault (core dumped)

Javaと同じノリで、nullを入れる事でどこにも参照が無い状態というのを 明示的に作り出しているだけのつもりなのですが、これだとダメなようです。 プロパティを使って実体への参照があるかどうかをチェックするのかしら? とか色々調べてみたのですが、この方法が良いとされたものかどうか、 他に代わる手段があるのかどうかが判らず。

2004/10/23

昼過ぎ起床。

DでOpenGL。gdcはCやC++といったコンパイラと同じ位置にあり、 生成するのはアセンブラソースである為、Cの関数とのインターフェースを 持ち合わせているのであれば、原理的にリンクした実行ファイルが動かない 理由はありません。一つ心当たりがあるとすれば、 先週、リンクを無理矢理行なう際、 何故だか判らないけどOpenGL系の関数が@付きの変な名前に置きかえられている のを知り、@付きになっていないgdcの出力したアセンブラソースを無理矢理 置き換えてリンクしたという点です。gccがどこを見て@付き関数名に置き換えて いるのかは判りませんが、それにはきっと意味があり、また、gdcが@付き関数名 になっていないのも、それはきっと意味がある事に違いないという事で、 自前で作成したC言語関数の中にOpenGL系関数を移して、D言語から D→Cラッパ→OpenGLの多段で呼び出しを行なってみた所、うまく動く事が 確認できました。よくはわかりませんが、 普通のスタティックリンクとダイナミックリンクとで、関数呼び出し手続きが 違うものを、無理矢理呼んでしまっている為、動くものは動くけど、 場合によってはスタックなどが壊れて、予期せぬ挙動を示しているものと 推測しています。
ちょっとダサい....いや、かなりダサいのですが、OpenGL系関数全てに ついてのラッパーを作成する事にしてみました。取りあえず、 gccのプリプロセッサを使って引っ張ってきたGL/gl.h,GL/glu.h,GL/glut.h に含まれる関数のリストから、perlで書いた使い捨てフィルターを使って 作成してみました。こういうのを作ってみると、意外とCのコーディングスタイル というのはパースが面倒で、例えば、型宣言なんかは「int」の様な 一単語のものと「unsigned int」の様なニ単語を使った宣言があり、 もうそれだけで、宣言部分を取り出すとか考えると、「あぁ、もうなんだか面倒!」 って感じでした。
で、色々ハマりながら一応完成。「gl*」の手前に「D_」というプリフィックスを 付けてしまったので、巷のソースがそのまま利用できなくなってしまったとか、 gl,glu,glutが一緒になってしまって良いのだっけ?という感じになってしまった とか、色々ありますが、一応動いている様です。そんな訳で、ソースだけ (一応サンプル付き)ですが御参考まで。0.82ベースでも0.102ベースでも どちらでもコンパイルできるハズです。

gllap_000.tar.gz

プログラムを書いている最中、何度も揺れてドキドキ。新潟地方の方が震源の ようですが、TV番組が軒並みニュースになっていったので、結構被害が 大きい模様。

そういや、ラッパーを使ったサンプルをビルドする為のMakefileを書いてて 気づいたのですが、D言語ではモジュールファイル(今まで呼び方がよく判ってなくて ヘッダファイルと言ってましたが(^^;)も、ソースも、拡張子は'.d'で同じ です。ここで、Cでラッパーを書いた時のソースファイル名をfoo.cとして、 それを呼び出す為の Dで使用するモジュールファイルをfoo.dとした時、 オブジェクトファイル.oを生成する時、アレ?どちらのソースから生成 すれば良いか区別付かないじゃんと思ったり。まぁ、CとDを混在させる事が なければ問題は無いのでしょうし、ソースファイル毎にオブジェクトの生成 手順を全て書けば良い訳ですが、ソースとソースが参照するモジュール(ヘッダ) とのニュアンスの違いがファイル名から区別が付かないのは、 なんとなく微妙な感じがしました。

2004/10/22

日付け越え。

そういや昨日観たTV番組の話。「松本紳助」というダウンタウン松本と 島田紳助のトーク番組で、生まれ変わりの話をしていました。 この話の始まりは、島田紳助が聞いた話で、「とある国の 少女が5歳になった時に突然、自分は生まれ変わりで、ある国のなんとか という両親の下に生まれたが、病気なった際にかかった医者が薬を 間違えてしまい死んでしまったのだと言い出した。そこで、ある国の 両親という人物に実際に確認してみた所、確かに少女の言う事は全て 合っており、少女が5歳になるまで全く接点が無かった為、 どうやら 記憶を引き継いだまま本当に生まれ変わったようだった」 という話があったそうだという事からでした。 この話を聞いた島田紳助は、「例えば同じ年齢を積み重ねている ハズなのに、東大に入れたり大臣になったりできるのは何故だろう、それは きっと生まれ変わりは何度か繰り返す事ができ、人生経験を何度も 積み重ねた人と、積み重ねが少ない人との差がそこに出ているからだ、 でなければ一度の人生で東大入ったり大臣になったりできるハズが無い」 というような事を言っておりました。生まれ変わりという現象が存在する 前提で話をする事自体がバカげているというのは置いといたとして、 世代を超えて経験が積み重ねられるという発想は面白いと思いました。 もしそういう現象があるのだとすれば、「生まれながらにして持ち合わせた センス」なんてのは、なるほど説明が付くように思います。 それが先週の話で、そんな話が出たので実際に番組中で色々な事を調べて みた所、先日、メジャーのイチローがシーズン最多安打記録を 破った事は記憶に新しいのですが、その記録を持っていた ジョージ・シスラーが死んだ年とイチローが生まれた年が偶然にも 同じ年だったという事が判ったらしいのです。これは本当にただの 偶然でしょうし、そもそも生まれ変わりという現象自体が科学的に 全く根拠無い話な訳ですが、番組中、島田紳助が「シスラーが 自分の記録を破る為にイチローに生まれ変わったんや」と言ってたのに、 思わず「そうかもぉ〜」と思ったりしました。勿論、仮に生まれ変わり という現象が実際にあったとしても、前世の経験の積み重ねだけで 今世をうまく渡ってゆけるとは思えませんけどね。 今の自分は生まれ変わり何回目? TANE自身はなんとなく3回目。 根拠は全くありません(笑。

2004/10/21

日付け越え。

昨日のビルドはうまくいってました。余計なゴミを置いてはダメという事の 様です。で、make install して、テストソースをコンパイルしてみたの ですが、エラーしまくり。文法チェックが変わったせいか、 Phobos(標準のランタイムライブラリ)のヘッダに対して、エラーしまくり なので、0.82のヘッダをそのまま使っているのが原因の模様。
そんな訳で、結局Phobosの方もコンパイルする事に。新しくビルドした gccを使わずにビルドしてエラーしたりしましたが、ほどなくして完了。 テストソースもエラーせずにコンパイルできました。

えーと、すっかり目的を忘れかけてますが、本題のOpenGLを使用したテスト コードをコンパイルした後、実行すると何やらエラーするというのが、 最新のコンパイラだとエラーしないのではないか?というのを確認するのが 目的でした。で、glutの方も「C style cast deprecated」なるエラーが 出るので直して、コンパイル&リンクを行なってみましたが、実行すると やっぱり赤○白×が出てうまく動かず。むーん。

でも、一応これで最新のgdcに追従する手順が判ったという感じ。

2004/10/20

台風接近の為、少し早めに帰着。

丁度22:00ぐらいから猛烈に雨が降り出してて、早く帰って助かったぁ と思ったり。

先日のgdcのビルドは完了していたり。make installして、いざ使って みたのですが、「object.dが見つからん」というようなメッセージが 出てコンパイルできず。確認してみると、何故かincludeヘッダにdの ヘッダが収められたディレクトリがインストールされておらず、 d/object.d というコンパイラが必ず参照するファイルが見つからなかった というのが原因の模様。既にCygwinのパッケージでインストールしてある ヘッダをコピーして、一応コンパイラ自体が動く事は確認できました。

で、続いて、 gdcページ からdmd 0.102ベースの最新gdc差分を拾って、再再度ビルド。

ビルド中、gdcの説明書を読んでいて、何気にサポートシステムの中に Mac OS Xが含まれていたりするのですが、PowerPCのネイティブコードも 生成できるという事なのかしら?と思ったり。

で、ビルド失敗(T_T)。古いソースをディレクトリ名を変えて gccディレクトリの下に置いといた所、その中が何故か参照されていて、 おかしな事になったらしい。古いのを完全に消して、またビルド。むー。

2004/10/19

日付け越え前に帰着。

先日ビルドしていたgdcはそれとなくできていたり。取りあえず インストール前に使ってみた所、libgccの3.4のものが無い為、 インストールしないと使えなさげ。でも、インストールすると、 不具合があったときに対処できなくなるので、prefixを変えて ビルドする事に。って、最初っから気づけよって感じですが(^^;

眠くて死亡。てゆーか、時間がかかり過ぎて待ってられません(^^;

2004/10/18

日付け越え前に帰着。

gdc-3.3.3のコアと、最新のdmdとでは、gdcの方が若干古いようなので、 最新への入れ替えが可能かどうかを試すべく、gdcをビルドすることに してみたり。
Cygwinパッケージより、gdcのソースをダウンロードしてみたり。 gccコアソースにD言語の差分を追加するという感じ。

途中で眠くなって死亡。

2004/10/17

昼過ぎ起床。

DでOpenGL。先日のコードを順にコメントアウトしながらどこで 死ぬのか見てみたり。gdbを使わないのは-mwindowsオプションを 指定するとgdbが使えなくなるからです(^^;
で、何故かOpenGL(正確にはGLUT)のコードを実行する前にずっこけて いたり。

int main(char[][] args){
    int argc = args.length;
    char** argv ;
    argv = new char*[argc];

glutInit()にargc,argvを渡す必要があるのですが、D言語では 引数はchar[][]型に入れる為、C言語風なargc,argvをわざわざ 作り直しています。で、この時の最後の行、「new char*[argc]」 を実行した所で何故か死ぬ模様。試しに、このコード単体で 動かしてみたのですが、特に問題無く動くような。

% cat test.d
import std.stream;

int main(char[][] args){
    int argc = args.length;
    char** argv = new char*[argc];

    for(int i=0; i<argc; i++){
        argv[i] = args[i];
    }

    for(int i=0 ; i<argc; i++ ){
        printf("%s\n",argv[i]) ;
    }
    return 0;
}
% gdc test.d
% ./a.exe aaa bbb ccc ddd
./a
aaa
bbb
ccc
ddd

仕方無く、C言語の関数でargvと同じ型で仮の割り当て領域を返す 関数をリンクしてみたところ、先に進むようになりました。 でも、ウインドが一瞬開いてSegfaultで死亡。むー。
更に、順にコードを潰していった所、glutReshapeFunc()で登録 した関数の中で使用しているgluPerspective()を実行した所で 死んでいるらしい事が判明。与える引数を即値にしてみるなど、 こねくり回してみたのですが、状況変わらず。取りあえず、色々削って みた所、ウインドは出るようになったり。んー、ちょっとした事で 動かないという予感がしますが、何故だか。

「鉄腕DASH」見たり。 以前、DASH村には 魚の棲める川が無いような事を書いたのですが、その事は一応指摘 されていたようで、その対策を行なっている事を知ったり。 単純に石を置いて沢の流れをせきとめるという方法のようなのですが、 たったそれだけで水深が結構深くなるようで、へぇと思ってみたり。
御当地食材の鰹のたたきにじゅるり。

2004/10/16

割と普通に起きて休出。

DでOpenGL続き。Webで見つけたポーティングの一つを使って gdcで使ってみたり。そのまま使用すると、アセンブラソース出力して みると、何故だか激しく関数名が置き換えられてしまったので、 importするファイルを見直し。version というキーワードでWin32と いうのが生きているようなのですが、gdcのimportファイルでは、

version (Win32){}
version (GNU) {}
else version (linux){}

となっていたのですが、ポーティングされたものは(GNU)の ケースが入っていませんでした。そこを追加し、extern (c)が 生きるようにすると、関数名そのままで出力されるようになりました。
で、実際にリンクしようとしたのですが、何故か関数が見つからず。 普通にgccでコンパイルできるOpenGLを使用したCソースを使って、 アセンブラソースを出力させてみた所、_func@0 の様に関数名の後ろに 何か付いていて、それが本当の名前という感じらしい事が判りました。 でも、何を元にしてCコンパイラはOpenGL系関数名を置き換えている のかが判らず。そんな訳で、/usr/lib/w32api の下にあるlibglut32.a, libglu32.a,libopengl32.aをobjdumpで逆アセンブルして、シンボル名 をgrepで抜き出して@付き関数名のリストを作り、perlでちょっこり 関数名置き換えプログラムを作成して、gdcで出力したアセンブラソース を加工してから、リンクしてみたり。リンクはできたのでOKと思いきや、 実行すると赤○白×でやっぱりダメ。うむー。

イノセンスの特典ディスクの方を観たり。 コメンタリーも観たのですが、実際に言われてみるまで判らない ような所まで描き込んであるだとか、実際の作業はえらく大変な事 だらけだったとか、アニメだと描ける現実には無いウソ絵が、 3DCGでやると(ウソ絵にならず)正しくしか描けないとか、 へぇと思う所が結構沢山あって、おもしろかったです。

2004/10/15

日付け越え前に帰着。

D言語でOpenGL。いくつかラッパーが存在するよう。 dmdで使用できるものはありますが、Cygwinのgdcで使用するのは マイナー過ぎの予感。

2004/10/14

日付け越え前に帰着。

D言語でOpenGLを使う方法を調べてみたり。
でも、猛烈に眠くなって死亡。

2004/10/13

出張。帰着。ふぅ。本日で出張生活一時停止。のハズ(^^;

そんな訳で、何気にUTF-8でテキストエディットを行なう方法を調べたり。 普段使用しているMeadowだと、普通にできるだろうと思っていたのですが、 これが何故か普通にはできなかったり。そこでWebを検索してみた所、 Muleで使用するパッケージを入れて、こねくりまわすという 面倒な手順が先頭に出て来たり。Emacsは20系から内部的にはUnicodeで 処理しているというのを聞いたことがあるのですが、そうだとすれば そんな面倒な事があるハズが.....という訳でしばらく探していると、

(require 'un-define)
(require 'jisx0213)
(set-language-environment	"Japanese")

というのを.emacsの先頭に書けば自動でエンコーディングを判定してくれる らしい。なんだ、簡単にできるじゃん!なのにMeadowではダメ的な情報ばかり が先に出てくるのか不思議。 実際に現在編集しているファイルのエンコーディングを変更するには、 「M-x set-buffer-file-coding-system」を使用して、コーディングに 「utf-8-unix」とかを指定すれば良い模様。因みにうちのMeadowでは、 コーディングリストに同じものが二つ並んでいるのが謎。

で、早速、D言語で試してみたり。

import std.stream;

int main() {
    stdout.writeLine("こんにちはD世界の表示");
    return 0;
}

てなのをSJISエンコーディングのソースでgdcに食わせてみると、

% gdc utf_test.d
utf_test.d(4): undefined escape sequence \\216

てな感じに未知のエスケープシーケンスでエラー。SJISでの「表示」が Hexで「95 5C 8E A6」、表示可能ASCIIで「.\..」てな感じなので、 エラーの通り。これをutf-8-unixにエンコーディングを変更して コンパイルすると、コンパイルは通るのですが、実行してみると utf-8そのままでターミナルに出力されてしまうので、文字コードに 自動判定機構の無いrxvtではダメダメ。

% ./a.exe | iconv -f utf-8 -t sjis
こんにちはD世界の表示

てな感じにすれば、一応表示はされますがどうもイマイチ。 なんて言うか、コンパイラが文字コードに対応しているというのは こういう意味を指すのか.....と思ったり思わなかったり。 因みに、Javaでも試してみたのですが、javacを使う場合は ソースファイルはSJISでもUTF-8でもどちらでも通りますが、 System.out.printlnを使った所では、D言語のそれと結果が同じで、 ソースの文字コードがそのまま出力されているという感じになりました。 そんな感じなので、Unicode対応のターミナルとか欲しくなってくる訳ですが、 Cygwin上のXはどうにも重い感が拭えないので、スタンドアロンで 動作するmltermとかないかなぁと思うこの頃。

ヤングジャンプで連載している「カッパの飼い方」のゲーム.....って、 マジっすか?

2004/10/12

出張。

2004/10/11

歯の痛みは大分引いたけど、頭痛がひどくて死亡。

買ったまま置きっぱなしになっていた「イノセンス」を観たり。 SACを観ているせいか、世界観の違いに少し違和感がありましたが、 んー、まぁ、悪くないんでない?そんな感じ(<偉そう)。 押井調の難しいセリフが多いのはアレですが、ストーリー自体は 難解でもなかったように思います(原作の「ROBT RONDO」がベース のようですが)。ところで、今回のは随分CGっぽさを残した映像に なっているように感じました。前のでは、CGを使っている事が 判らない様に使うという点を強調していたようにも思いますが、 今回のは背景が何やら殆どCGで、っぽさ溢れまくりという感じ だった様に思います。ちょっと意外に感じました。

手品の番組を観たり。前田知洋氏のどう見てもそのトリックの 判らない鮮やかなテクニックに驚いてみたり。仕掛けがあるのは 明らかなのに、それが判らないというのはやっぱり不思議。あと、 Dr. SAWAという、本業は歯医者さんなのに、凄いテクニックを 持った人が居るというのを、時々TVの手品番組や特集などで 聞くことがあったのですが、その本人が出ていたり。 いや、もうね、なんで歯医者さん?そんな感じでした。

歯痛で連休をフイにしてしまった感じ。ちぇっ。

2004/10/10

一日中、歯痛に苦しみ死亡。

2004/10/09

あー、よく寝たと思ったら、まだAM9:30前。寝るのが早かったからか? と思ってTVをつけたら、9:30始まりの王様のブランチがやってたり。 よくよく時計を見てみると止まっている罠(^^;。結局、昼過ぎ起床。

除々に歯が痛くなってきて、起きてるのも億劫になってきたり。

2004/10/08

出張。帰着。ふぅ。

歯が痛くて死亡。

2004/10/07

出張。

2004/10/06

出張。

2004/10/05

出張。

2004/10/04

日付け越え前に帰着。

モリモリとD言語に興味が湧いてきた所で、ドキュメントをよく読んでみる 事にしました。で、例に載っているソースをコンパイルしてみたり。 コンパイラはCygwinパッケージに含まれる gcc-3.3.3に取り込まれたらしい gdcを使用してみました。
載っている例がなんかオブジェクト指向言語っぽくなかったりしたので、 基本的なスタイルがイマイチ判らなかったりするのですが、C言語っぽく 書く事が許されている感じ。この点は、全ての実装をクラスで行なう という、記述の一貫性があるという意味で、Javaの方が良い感じが します。ただ、どのクラスのmainメソッドを実行開始点にするのかを 指定する必要があるのが面倒っぽい感じはしますけれどもね。

文字列操作については、C++をもう少しPerl寄りにした感じ。 ただし、切ったり繋げたりというのは普通にできそうですが、 正規表現で文字列マッチや変換を行なったり、文字列の一部を マッチ条件から取り出したり(JavaのMatchクラスでいう「前方参照」のような 動作)、char型以外の型からchar型に自動変換したり、sprintf()っぽい 事や、split()っぽい事はできなさそうな予感。まぁ、そう動くものを 書けば良いだけなのかも知れませんが。

C言語で書いた関数とリンクする練習してみたり。ふむー、簡単。

2004/10/03

昼頃起床。

TVなど観ながらダラダラ過ごしたり。
先日買って、そのままだったファミ通WaveDVDなど観たり。Xboxでサイヴァリア2とか。 アーケードでも見た事なくて、DCで出ているらしいのですが、それも 見た事無いという、幻に近い存在に感じているのは、私だけでしょうか(^^;
全部見終わった後で気づいたのですが、右下に「ALL PLAY」ボタンが付いてて、 流し見できる様になってました。これ、個人的に密かに切望していたボタン でして、「いちいち選ぶの面倒臭いなぁ、どうせ全部見るのだから全再生 できれば良いのに」といつも思っていたのです。あぁ、もっと早く気づけば 良かった。

結局、ぐうたら過ごして一日終了。

2004/10/02

昼前に起床。

povray-3.6.1 をppcクロスコンパイルしてみたり。 povray-3.5の時はjpegやtiffなどのユーティリティライブラリは、 外で持つ方式だったのですが、3.6からは自アーカイブ内に各種 ユーティリティライブラリを取り込んでいる様です。 これにより、ユーティリティのバージョンやインストールされている かどうかに関係無く、ビルドできるという感じになっているみたい。 で、configureをCygwinネイティブで通した後、Makefileを手で書きかえる 作業を行なって、ビルドしてみました。ソースには一切手を入れる事 なくビルドできる感じ。で、ppcsim上で実行してみて、取りあえず OKそう。
因みに、以前、gcc-3.4.2のppcクロスコンパイラと同じ コンパイル環境で、ビルドしたpovray-3.50bでレンダリングした 実行結果と、今回のpovray-3.6.1での実行結果を比較した所、 レンダリングにかかる実行命令数は、5%ばかり増えている様です。 もう少しレンダリングに時間のかかるシーンファイルを使用すれば、 コアかファイルIOかそれ以外のどこか、で命令数を食っているか判る かも知れません。なんとなくコアっぽい予感はしますが。

Javaプログラム。取りあえず、一通り繋げて何か作ろうと 仕込みを入れていたのですが、リストにバグが入っていて悩んで みたり。最後の一つのリスト要素を削除した際、nullを入れて リスト自体の無効化を行なっていたのですが、その存在しないハズの リスト要素に含まれる子インスタンスのメソッドを呼ぼうとすると、 何故かハングするというものです。 nullポインタアクセスの例外になっても良さそうな 感じがするのですが、nullを入れたリスト要素への参照では無く、 nullを入れる事で参照不能になるハズの子インスタンスのアクセスと いうのが、なんとなく関係してそうな感じ。
他、先日javacはソースとクラス名との時間関係を見て、必要 であれば勝手にコンパイルする仕様になっていると書きましたが、 時々、そうでもない場合があって、「あれ?変更したつもり なのに動作が同じでなんで?」という事がありました。それでも、 コンパイル自体の時間がそれほど長くないので、クラスファイル を全て消して最上位クラスのコンパイルコマンド一回実行で済むのは、まぁ、 お手軽ではありますが。

SAI 4版が出ているので試してみたり。レイヤーが追加/削除できる様に なっていたり、細かな部分での入れ込みがありますが、水彩筆の ウェットモードが、今までに無いモードの一つとして実装された模様。 色々感触を掴んでいる最中。

2004/10/01

出張。帰着。ふぅ。

本物お仕事の合間にImageIOの使い方などを練習して、なんとなく 作法は掴んだり。で、それを元に家でも同じ事をやってみたのですが、 何故かImageIOを使用すると、getImage()を使うよりも倍以上 遅くてぐったり。何故だかよく判りませんが、毎回ファイルから デコードしながらイメージを貼り付けているような、そんな感じに 見えなくもありません。

出張中に「Java 謎+落とし穴 徹底解明」という本を読みました。 ちょっと毛色の変わった本で、「Javaって本当に良いのか?」という 視点で、一般的に言われている誤信などにも触れています。 特に、Javaにはポインタは無いと言われている点について、 JavaのホワイトペーパーのOverviewに「Javaにはポインタがない」 と書いてある、同じ文書の別の場所に「CやC++とは異なるポインタが ある」と読めるような説明があるというのに、興味を持ったり。 いわゆる「参照」は「ポインタ」と概念的には同じな訳ですから、 私もポインタが無いというのは言い過ぎと思います。 また、Java Programmer's FAQ なる文書に、「Javaには ポインタがないそうですが、連結リストはどう作ったらよいのですか?」 という質問があるそうなのですが、これ、実は私も同じ疑問を抱いて ました。結局、「参照」が「ポインタ」のような別名を付ける 機能を果たすので、実際には連結リストを書く事ができるというのが 答えなのですが、 「ポインタが無い」を文字通りに解釈すると、一つの記憶領域の実体は 一つの名前(変数名)でしか呼べないのだから、あだ名(ポインタ)が 使えない以上は、連結リストは書けません、と解釈するのは当然なように思います。 そんな訳で、先日TANEが勝手に想像した、ガベージコレクタとポインタの 話を書いたのですが、全く同じ疑問に対して、同じような答えを、 この本で得られたので、自己満足満足ぅ(^^;

でも、うれしいかうれしくないかで言うと、Javaはあまり うれしくないというのが、やっぱりTANE的印象です。 うれしいと感じない点は、

  1. JavaVM上で動作するのでプラットホームを選ばないと言いながらも、 JavaVMは動作するプラットホームを選ぶ(例えば新しいOSで動かすにも Sunの意向を伺う必要があるでしょう)ので、「"理論上は"プラットホーム を選ばない」が正しい感じ。そう思うと、なんか良い事だけ書かれた カタログを読んでいる感じがうれしくない。
  2. チューニングのやり甲斐がなんとなく無い。ガベージコレクタの性能 を強調するのは「売り」なので良いのですが、他はどう考えても VMの性能に依存しているので、最新のプロセッサ上でエミュレータ を動かして、そのエミュレータ上で一生懸命速いプログラムを書こうと しているような、本末転倒的な感じが釈然としなくてうれしくない。

私の場合、職業プログラマーではありませんので、一般的な ソフトウェア開発での実務的なメリットは、全く評価基準に 関係無い所だったりします。うれしさを優先するのは、私が うれしがりだからです(^^;
そんな訳で、ネイティブのCPUコードを吐いて、ガベージコレクションが 使えて、特殊なラッパー無しでC言語ライブラリとインターフェースが 取れて、インラインアセンブラで最悪の対応も可能という、 「D言語」 に、遅ればせながらモリモリ興味が湧いてきている感じです。

そういえば、javacコンパイラでソースをコンパイルする際、 最上位に相当するクラスを含むソースをコンパイルすれば、 その最上位のクラスの中で参照しているクラスを含むソースを勝手に 探してコンパイルするというのは、少し前にgcjとの比較を行なって いる際に知ったのですが、この機能が生きていると、 結局ソースの依存関係はjavacが全て面倒を見るという事になります。 そう考えると、ビルドツールであるAntは、実は大した仕事はして ないのじゃなかろうか?という気がしてきました。 javacの様に気の利いた(むしろお節介な)コンパイラではない、 普通のCコンパイラの場合だと、そういう訳にはいかないと思うの ですが、AntでCプログラムのビルドをやらせろうとした場合、 果たしてmakeよりも効率的に依存関係を記述できるのじゃろうか? と思いました。
そんな訳で、Antを使ってJava以外の言語のビルドもウハウハと 言ってる人が居ないかなぁとWebをさまよっていると、 antshellなるものを 発見したり。基本はAntの起動を良い感じにするshellライクな ツールみたいなのですが、Javaのクラスをコマンドラインライクに 実行できるという機能も備えているようで、 先週JavaVMの起動をラッパーで必ず 包む必要があるのがダサいと言ったのに対する答えの一つな 感じがしました。やっぱ同じ事思うよね?とか思ったり思わなかったり (<どっちや)。あぁ、で、AntでJava以外の言語のビルドでウハウハ な情報は今回は得られませんでした。


TOP PREV