Sep 23, 2008

Yellow Dog Linux on PS3 で GL Excess / Ruby


暇なので Yellow Dog Linux on PS3 を整備して遊んでいました。 以下に GL Excess / Ruby を動かすまでの作業をメモしておきます。
  • root で作業してください。
  • Yellow Dog Linux 6.0 は PS3 にインストール済みであるとします。
まずは /etc/X11/xorg.conf を編集。 GLX 拡張をロードするため、"Module" セクションに次のように追記します:
Section "Module"
       Load  "dbe"
       Load  "extmod"
       Load  "fbdevhw"
       Load  "freetype"
       Load  "type1"
       #Load   "dri"
       Load  "glx"  # ←この行を追記
EndSection
X Window が起動中の場合、編集終了後にを再起動を (Ctrl+Alt+Backspace)。まだ起動していないなら startx を。問題なく起動することを確認してください。
次に freeglut のインストール。パッケージ化されているのですぐに終了します:
[root@localhost ~] yum install freeglut
...
[root@localhost ~] yum install freeglut-devel
続いて Ruby 1.9.0-4 をビルド&インストール。すでに Ruby 1.8.5 がインストールされているので、ここでは Ruby 1.9 の関連プログラムが ruby19 や gem19 といった名前となるよう、--program-suffix で指定しています:
[root@localhost tmp] wget ftp://ftp.ruby-lang.org/pub/ruby/ruby-1.9.0-4.tar.bz2
...
[root@localhost tmp] tar xvjf ruby-1.9.0-4.tar.bz2
...
[root@localhost tmp] cd ruby-1.9.0-4
...
[root@localhost ruby-1.9.0-4] ./configure --program-suffix=19
...
[root@localhost ruby-1.9.0-4] make && make install
ここまでで /usr/local/bin/ruby19 や /usr/local/bin/gem19 などが利用できるようになっています。 あとは ruby-opengl のインストール。ソースパッケージのダウンロード、ビルド、拡張ライブラリのインストールが自動的に実行されます:
[root@localhost ~] gem19 install ruby-opengl
GL Excess / Ruby を動かしてみます。一般ユーザーに戻って作業しても OK です。
[lt140@localhost tmp] wget http://sites.google.com/site/ltsevenscore/archives/glxsruby-20091223.7z
...
[lt140@localhost tmp] 7z x glxsruby-20091223.7z
...
[lt140@localhost tmp] cd glxsruby
...
[lt140@localhost glxsruby] ruby19 glxs.rb -s 9
写真は PS3 上の X Window で動く GL Excess / Ruby。 GPU Acceleration が効かないので遅いです。酔狂もいいところ。 ちなみにディスプレイは BRAVIA 。遊び道具をありがとうございます>ソニーグループ御中



Yellow Dog Linux 6.0 on PS3 : 設定等のメモ


ランレベルは 5 から 3 に変更

/etc/inittab を開いて、
id:5:initdefault:
となっている行を以下に変更する:
id:3:initdefault:

Fluxbox ウィンドウマネージャを導入

メインメモリ 256MB のマシンに Enlightenment, GNOME は厳しいので。
[root@localhost tmp] wget http://prdownloads.sourceforge.net/fluxbox/fluxbox-1.0.0.tar.bz2
...
[root@localhost tmp] tar xvjf fluxbox-1.0.0.tar.bz2
...
[root@localhost tmp] cd fluxbox-1.0.0
...
[root@localhost fluxbox-1.0.0] ./configure
...
[root@localhost fluxbox-1.0.0] make && make install
...
インストール終了後は ~/.Xclients に以下の 1 行を記述する:
/usr/local/bin/fluxbox
これで startx 直後に Fluxbox が起動される。

各種サービスを off に

サーバ用途として利用するつもりがないので、 sendmail などの不要なサービスを起動しないように設定:
[root@localhost ~] chkconfig --level 35 sendmail off
...
DHCP で取得した情報が上書きされてしまうように見えたので、 NetworkManager, NetworkManagerDispatcher も起動しないように設定。
[root@localhost ~] chkconfig --level 35 NetworkManager off
...
[root@localhost ~] chkconfig --level 35 NetworkManagerDispatcher off
...

ゲーム OS での再起動は ps3-boot-game-os

[root@localhost ~]$ /usr/sbin/ps3-boot-game-os

Aug 8, 2008

Ruby/SDL をビルド


素の Ruby/SDL を Visual C++ 2008 Express Edition でビルドするまでのメモです。 TTF や draw_line などを使用しているサンプルは動きませんのでご注意を。

用意するもの

  • Visual C++ 2008 (Express Edition SP1)
  • OpenGL
    • include : c:/Program Files/Microsoft SDKs/Windows/v6.0A/Include
    • lib : c:/Program Files/Microsoft SDKs/Windows/v6.0A/Lib
  • DirectX SDK
SDL のビルドに必要です。March 2009 を利用しました。
D:\tmp>ruby -v
ruby 1.9.1p243 (2009-07-16 revision 24175) [i386-mswin32_90]
d:/ruby19 にインストール & d:/ruby19/bin にパス設定済みとします。

ビルドとインストール

SDL
  • VisualC.zip を展開、SDL.sln を開いて Release ビルド。
  • dsound.h が無いとビルドエラー。⇒ 要 DirectX SDK
できあがった VisualC/SDL/Release/SDL.dll は d:/ruby19/bin にコピーしておきます。
Ruby/SDL
Makefile を書くのも面倒なので、sdl.so を作成するための新規プロジェクトを作成して対応します。
rubysdl-2.1.0 を展開したフォルダに 新規プロジェクトを作成します。ここでは `VCBuild' という名前にします。

DLL を作りたいのでそう選択します。空のプロジェクトに設定して、ソースコードの追加を後で行います。


既存の要素として Ruby/SDL のソースコードをプロジェクトに追加します。


プロジェクトのプロパティを設定する前に下準備をします。VCBuild フォルダの中に `sdl.so.def' という名前のテキストファイルを新規作成します。


内容はこちらの2行だけです:


ここから VCBuild プロジェクトのプロパティ設定を行います。ソリューション構成は Release にした 上で、まずは "C/C++ > 全般 > 追加のインクルード ディレクトリ" に以下のように記入します(各自の環境で適宜読み換えてください):


記入するのは SDL と Ruby のインクルードファイルが配置してある場所です。次に "C/C++ > プリプロセッサ > プリプロセッサの定義" に追記します:


ENABLE_OPENGL と追記しました。次は "リンカ > 全般 > 追加のライブラリ ディレクトリ" にパスを記入します:


SDL.lib, SDLmain.lib そして Ruby のエクスポートライブラリの場所を指定します。 次は "リンカ > 全般 > 出力ファイル" で名前を 'sdl.so' と明記します。


次は "リンカ > 入力 > 追加の依存ファイル" :


最後は "リンカ > コマンドライン > 追加のオプション" に sdl.so.def を使用するよう記入しておきます。


ビルドすると 'VCBuild/Release' に sdl.so が作成されます。


… Makefile 書くのとどっちが面倒だったろう?(^^;
それはそれとして、この DLL を含め、 Ruby/SDL のライブラリファイルを既定の場所へコピーしてインストール完了です。
  • VCBuild/Release/sdl.so
    • -> d:/ruby19/lib/ruby/site_ruby/1.9.1/i386-msvcr90 にコピー
  • lib/sdl.rb, lib/rubysdl_aliases.rb, lib/rubysdl_compatible.ver1.rb
    • -> d:/ruby19/lib/ruby/site_ruby/1.9.1/ にコピー
コマンドラインから実行:
D:\tmp\RubySDL\rubysdl-2.1.0\sample>ruby randrect.rb



今回ビルドしたのは素の SDL のみなので、フォントや高レベルの描画機能(draw_line, etc.)は 動作しませんのでご注意を。

Aug 3, 2008

Ruby 1.9.0-3 : インタプリタ DLL を C から呼ぶ例

(2010-08-29 追記 : 以下の記事は古くなっています。こちらが参考になるかもしれません。 http://sites.google.com/site/ltsevenscore/ruby/tips/interpreter_dll )


  • ruby_options が値を返すようになっている
  • ruby_run という関数がない
など、Rubyの初期化・実行に関する README.EXT の内容は現状に追いついていないようです。
そのようなわけで、Ruby 1.9 を外部から利用する方法を少し調べてみました。
  • アプリケーションに Ruby を組み込みたい
  • rubyw.exe に代わる前処理プログラムを作りたい
といったときに役立つかもしれません。
利用したのは Ruby 1.9.0-3です。 これを VC++ 2008 でビルドした msvcr90-ruby190.dll を C プログラムから利用してみます。
こちらがアプリケーションのソースコード。必要最小限のエントリーポイント を取得した後、インタプリタの初期化と実行に移っています。
UseRubyDLL.c:
#define WIN32_LEAN_AND_MEAN
#include 

#define APP_NAME                "UseRubyDLL.exe"
#define RUBY_DLL_NAME           "d:\\ruby19\\bin\\msvcr90-ruby190.dll"
#define RUBY_SCRIPT_NAME        "script.rb"

HINSTANCE ruby_dll;

/* from include/ruby/ruby.h */
void  (*ruby_init)( void );
void  (*ruby_sysinit)( int*, char*** );
void* (*ruby_options)( int, char** );
/* from include/ruby/intern.h */
void  (*ruby_init_loadpath)( void );
int   (*ruby_run_node)( void* );

void
WinMainCRTStartup()
{
    /* Dummy arguments for ruby_sysinit(). */
    int         sysinit_argc = 0;
    char**      sysinit_argv = NULL;

    /* Manually construct interpreter arguments. */
    int         app_argc = 3;
    char*       app_args[3];
    char**      app_argv = app_args;
    app_args[0] = APP_NAME;
    app_args[1] = RUBY_SCRIPT_NAME;
    app_args[2] = "See ya.";

    ruby_dll = LoadLibrary( RUBY_DLL_NAME );
    if ( ruby_dll )
    {
        ruby_sysinit       = (void (*)( int*, char*** ))GetProcAddress( ruby_dll, "ruby_sysinit" );
        ruby_init          = (void (*)( void ))GetProcAddress( ruby_dll, "ruby_init" );
        ruby_init_loadpath = (void (*)( void ))GetProcAddress( ruby_dll, "ruby_init_loadpath" );
        ruby_options       = (void* (*)( int, char** ))GetProcAddress( ruby_dll, "ruby_options" );
        ruby_run_node      = (int (*)( void* ))GetProcAddress( ruby_dll, "ruby_run_node" );

        ruby_sysinit( &sysinit_argc, &sysinit_argv );
        ruby_init();
        ruby_init_loadpath();

        ruby_run_node( ruby_options( app_argc, app_argv ) );

        /* NOTE: After the execution, +ruby_run_node+ automatically
           calls +ruby_cleanup+. So there's no need to explicitly call
           Ruby's finalizer here(otherwise cause disaster).
         */

        FreeLibrary( ruby_dll );
    }
}
上記の ruby_*() 系関数の利用方法は Ruby のソースコード(winmain.c, eval.c, etc.)から把握したものです。 当然ですがインタプリタ DLL の場所など、ハードコードした部分は適宜変更する必要があります。
アプリケーションから呼び出すスクリプトはこちら。インタプリタ DLL の場所 次第では、標準ライブラリ(ここでは matrix.rb)jの require に失敗しますの でご注意を。
script.rb:
require 'matrix'
File.open( 'result.txt', 'w' ) do |f|
  f.puts Time.now
  f.puts Vector[rand,100*rand,10000*rand]
  f << ARGV
end
ビルドによって生成された UseRubyDLL.exe を以下のように実行します。 script.rb は同じ場所にあるものとします。
$ ./UseRubyDLL
実行すると同じ場所に result.txt ができているはず。以下が結果の一例です。
result.txt(例)
2008-08-03 18:52:16 +0900
Vector[0.434646515113465, 27.44515575993, 9534.51425972162]
["See ya."]
ちなみにビルド用の Makefile はこちら。実行ファイルを小さくするため、あえて Cygwin gcc (gcc -mno-cygwin -mwindows) を利用してみました。
Makefile:
TARGET = UseRubyDLL.exe
SRC = $(TARGET:exe=c)
OBJ = $(TARGET:exe=o)

CC = gcc -mno-cygwin -mwindows
CFLAGS = -Wall -Os
LDFLAGS = -lkernel32 -nostdlib

all: $(TARGET)

$(TARGET): $(OBJ)
 $(CC) -o $(TARGET) $< $(LDFLAGS)
 strip $(TARGET)

clean:
 rm $(OBJ) $(TARGET)

.c.o:
 $(CC) $(CFLAGS) -c $<
手元での結果はこちら:
$ gcc --version
gcc (GCC) 3.4.4 (cygming special, gdc 0.12, using dmd 0.125)
Copyright (C) 2004 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


kazuwe@kazuwe-PC ~/UseRubyDLL
$ ls -l UseRubyDLL.exe
-rwxr-xr-x 1 kazuwe None 2560 Aug  3 18:58 UseRubyDLL.exe
ちょっと心配になるくらい小さくなるものですね :-)

参考

  • embedding Ruby 1.9.0 inside pthread
  • BDS2006(C++Builder)からRubyを使う (山本隆の開発日誌)

Jul 20, 2008

RMath

今年1月に書いておきながら、 そのまま忘れて半年放置していた 3D CG 向けの数学関数の拡張ライブラリを公開しておこうと思います。
RMath といいます。
RMath は行列(3x3,4x4)、ベクトル(3要素,4要素)、クォータニオンの各クラスを含んだ拡張ライブラリです。 デバッグ用に同じインタフェースを持った Ruby 実装版も同梱しています(RMath.rb)。
ライセンスは zlib/libpng としました。
リファレンスやサンプルが少ないので、それらの充実が当面の課題ですね。
(2009-12-26 URLを新しいものに修正しました)

Jul 6, 2008

takeown, icacls コマンド

Windows Vista での chown / chmod コマンドに相当するものです。
訳あって C ドライブの Vista (Home Premium) をインストールしなおしたところ、 以前から D ドライブ側に置いていたファイルへのアクセスに支障が出てしまいました。
具体的には:
  • 消せないファイルが多発。
  • Cygwin 系コマンドでの操作が軒並み ``Permission denied'' に。
OS からは別な(しかももう存在しない!)ユーザーの所有物とみなされているのが原因です。
この問題を次のようにして解決してみました。
1. コマンドプロンプトを「管理者として実行」する
``C:\Windows\System32\cmd.exe'' のアイコンを右クリックし、「管理者として実行(A)」で起動。

2. 作業するディレクトリに移動
ここでは ``D:\cygwin'' とします。
C:\Windows\system32>d:

D:\>cd cygwin

D:\cygwin>
3. ファイルの所有権を取得
takeown コマンドを実行します。 ``/f '' がファイル名の指定。``/r'' は再帰的に実行することを指定するものです。
D:\cygwin>takeown /f * /r

成功: ファイル (またはフォルダ): "D:\cygwin\bin" は現在ユーザー "lt140-PC\lt140" によって所有されています。

成功: ファイル (またはフォルダ): "D:\cygwin\cygdrive" は現在ユーザー "lt140-PC\lt140" によって所有されています。

成功: ファイル (またはフォルダ): "D:\cygwin\Cygwin.bat" は現在ユーザー "lt140-PC\lt140" によって所有されています。

成功: ファイル (またはフォルダ): "D:\cygwin\Cygwin.ico" は現在ユーザー "lt140-PC\lt140" によって所有されています。

成功: ファイル (またはフォルダ): "D:\cygwin\dev" は現在ユーザー "lt140-PC\lt140" によって所有されています。

...(以下略)
4. アクセス権を操作
icacls コマンドを実行します。 複雑なオプションを多数受け付ける高機能なコマンドですが、「ユーザーに指定したパス以下のフルコントロールを与える」のであれば ``icacls <パス名> /grant <ユーザー名>:F /t'' だけで終了です。 フルコントロール可能な状態にしたくない場所での実行には注意してください。その場合は ``:F'' とした部分を変更することになります。``icacls /?'' で詳細を確認してください。
D:\cygwin>icacls D:\cygwin /grant lt140:F /t
処理ファイル: D:\cygwin\bin
処理ファイル: D:\cygwin\cygdrive
処理ファイル: D:\cygwin\Cygwin.bat
処理ファイル: D:\cygwin\Cygwin.ico
処理ファイル: D:\cygwin\dev
処理ファイル: D:\cygwin\etc
処理ファイル: D:\cygwin\lib
処理ファイル: D:\cygwin\setup.exe
処理ファイル: D:\cygwin\tmp

...(以下略)
これで無事に読み書きできるようになりました。
…OS は忠実に自分の仕事をこなしているだけなのですが、自分がPCの管理者かつ唯一の利用者であるという状況では正直切ないですね。

Jun 8, 2008

マニフェスト関連


Visual C++ ファイルの再配布

Visual C++ ライブラリ DLL (MSVCR80.DLL など) に到達できた場合 (アプ
リケーションのローカル フォルダまたはシステム フォルダにインストール
されている場合など)、次のメッセージが表示されます。

R6034 An application has made an attempt to load the C runtime library incorrectly.

C/C++ 分離アプリケーションおよび side-by-side アセンブリのトラブルシューティング

すべての DLL がバイナリに埋め込まれたマニフェストを持つようにすることを
お勧めします。DLL が LoadLibrary 呼び出しで読み込まれる場合、外部マニフェストは
無視されます。

方法 : マニフェストを C/C++ アプリケーションに埋め込む

C/C++ アプリケーション (またはライブラリ) では、そのマニフェストを
最終的なバイナリに埋め込んでおくことをお勧めします。これにより、ほとんどの
シナリオで実行時の適切な動作が保証されます。