上へ

開発メモ

2001/08/28 中国出張その2(1)
再び中国シンセンの蛇口 に出張。
前回はホテルで鍵が開かないトラブルが頻発して、毎日のようにフロントに行って、 鍵を見せて「不開(プーカイ)」【Don't work?】「Yes...じゃなくて Don't work!」 (←否定文を肯定してしまう日本人) とやっていたので、顔を覚えられていて、チェックインに行ったら見つけられるなり 笑顔で手を振られてしまいました。

基本的に話が通じないので、とりあえず笑ろうとけ戦略でいったのがうけたらしい。
2001/08/29 中国出張その2(2)運ちゃんと仁義無き争い
今回は出張期間中を通してホテルから会社へのバスが満席状態だったため、 ほぼ毎日タクシーで出社することになりました。

ホテルから会社まで、タクシーのメーター(規定料金)で走ると大体 30元ちょっと(約500円)かかる のですが、蛇口では外国人相手の場合、まずお釣はくれないし、メーターを倒さずに走って、 50元とか要求してくる運ちゃんもいます。

中国人は日本人より個性の幅が広く、真面目な人から、酔っ払ったような運ちゃん、 どう見ても写真と顔が違う運ちゃん、と、いろいろいるので、今回の運ちゃんは大丈夫なのか? と、毎日頭の痛い問題でした。

ちなみに地元のおねーちゃんに言わせると、ホテル会社間なら交渉して25,30,35元なら乗ってよし、 40元でも高いし、50元はとんでもない、とのこと、ようするにボラれているらしい。 それはそうと、地元のおねーちゃん下手すると規定料金以下で乗ってないか?(^^;

・・・何の開発メモなんだか。(^^;
2001/08/30 中国出張その2(3)自作PC
現在は、日本から中国にパソコンを輸出する確実なルートが無いので、 設備で使用するパソコンも現地調達を模索しているところなのですが、 設備でよく使用している Matrox の画像取込ボードが 相性に非常にシビアで 大きな不安材料でした。

そんな時、ちょうど同じ時期に立ち上げていた別の設備が Matrox の画像取込ボードを使っていて、 現地で入手が容易なメーカー製パソコンとどうやっても相性が悪く、ついに電気街に行って マザーボードから購入することになりました(笑)。

作者がご意見番ということで(実は詳しくないんだけど(^^;)設備担当者と通訳と 値下げ交渉役(笑)と一緒に電気街に・・・、作者は中国到着日から 連日の残業とタクシー疲れ(笑)がでて、途中からダウンしていましたが、 他のメンバーで CPU、マザーボード(メーカー違いをいくつか)、メモリ、ケース、電源と 買っていました。

結果としては組み立てPCで Matrox の画像取込ボードがちゃんと動きました。 現地技術スタッフも部品購入から関わって、組み立てもかなり楽しそうにするので、 うまくいけば今後パソコン調達で苦労することはなくなるかも。
2001/09/04 中国出張その2(4)
Linux、Kylix を知っていた驚異の現地技術スタッフは秀才揃いの現地技術スタッフの中でも 特別製だったらしい、よかったこんなやつが一般人じゃなくて。
あんなのが一般人だったら転職を真剣に考えないといけないところだった(爆)

前回、現地技術スタッフがマクロも無いエディタでちまちまと単純作業をしていたので、 フリーのエディタを紹介していったのですが、予想通り、今でもちまちまやっていました。(笑)

ここらへんの頑固さは万国共通らしい。
2001/09/05 中国出張その2(5)
もう他をかまっている余裕は無い、仕事、仕事。
2001/09/13 帰国
テロで成田空港は何十年に1度の警戒態勢らしい、行列が長いんだろうなと思って いたのですが、香港の手荷物検査や、成田の到着では普段と それほど変わったことも無く普通に通れました。
2001/09/24 出張成果
今回の出張で Kylix 対応 I/O ポートアクセスドライバと InputForms の Grid 関係を少し拡張したので、時間が出来たら公開予定。

アプリの多国語対応について、漠然と案が出てきたので、そのうち実験予定。 Kylix の開発者ガイドに書かれている方法はあまり現実的ではないと思う。

久々の開発メモネタだ。(^^;
2001/09/28 アプリ多国語対応実験
Delphi,Kylix での多国語対応は resourcestring を使用するということになっていて、 実際に動的にロードする手段も提供されています。
プログラム中に書くコードはこれで対応できるのですが、DFM(xfm) ファイル中に書かれる 文字列はそうもいかないので、DFM(xfm) ファイル中の文字列を動的に変換する実験をしました。
procedure LoadLocale(AComponent: TComponent; const FileName: string);
// AComponent に FileName の設定を反映する
  procedure ReplaceCaptions(AComponent: TComponent; const Map: TStrings);
    function StrToText(S: string): string;
    begin
      if (Map.IndexOfName(Trim(S)) = -1) then
      begin
        Result := S;
        Exit;
      end;
      with (TStringList.Create) do
      try
        CommaText := Map.Values[Trim(S)];
        if (Count = 1) then
          Result := Strings[0]
        else
          Result := Text;
      finally
        Free;
      end;
    end;
  var
    I: Integer;
  begin
    if (AComponent is TControl) then
      TLabel(AComponent).Caption := StrToText(TLabel(AComponent).Caption);
    if (AComponent is TMenuItem) then
      TMenuItem(AComponent).Caption := StrToText(TMenuItem(AComponent).Caption);

    for I := 0 to AComponent.ComponentCount - 1 do
      ReplaceCaptions(AComponent.Components[I], Map);
  end;
var
  Map: TStrings;
begin
  Map := TStringList.Create;
  try
    Map.LoadFromFile(FileName);
    ReplaceCaptions(AComponent, Map);
  finally
    Map.Free;
  end;
end;

procedure SaveLocale(AComponent: TComponent; const FileName: string);
// AComponent 設定を FileName に保存する
  procedure GetCaptions(AComponent: TComponent; var Map: TStrings);
    function TextToStr(S: string): string;
    begin
      with (TStringList.Create) do
      try
        Text := S;
        Result := CommaText;
      finally
        Free;
      end;
    end;
  var
    I: Integer;
  begin
    if (AComponent is TControl) then
      Map.Values[TextToStr(TLabel(AComponent).Caption)] := 
        TextToStr(TLabel(AComponent).Caption);
    if (AComponent is TMenuItem) then
      Map.Values[TextToStr(TMenuItem(AComponent).Caption)] :=
        TextToStr(TMenuItem(AComponent).Caption);

    for I := 0 to AComponent.ComponentCount - 1 do
      GetCaptions(AComponent.Components[I], Map);
  end;
var
  Map: TStrings;
begin
  Map := TStringList.Create;
  try
    GetCaptions(AComponent, Map);
    Map.SaveToFile(FileName);
  finally
    Map.Free;
  end;
end;
以上のコードをまるまるコピーして、
  SaveLocale(Application, 'en_US.ISO8859-1');
を実行するとアプリ DFM(xfm) 中の文字列を抜き出した en_US.ISO8859-1 というファイルが出来ます。
Form1=Form1
Button1=Button1
&help=&help
そのファイルを ja_JP.SJIS にリネームしてエディタで編集します。
Form1=フォーム1
Button1=ボタン1
&help=ヘルプ(&H)
出来た ja_JP.SJIS ファイルを読ませると変更が反映されます。
  LoadLocale(Application, 'ja_JP.SJIS');
TForm1.FormShow(Sender: TObject) あたりでアプリ起動時に1度だけ実行する使い方を 想定しています。LoadLocale/SaveLocale の引数を Application から例えば Form1 とすると Form1 に含まれる文字列だけ処理します。

・・・それにしてもえらいローテクな。(--;
Caption に resourcestring が指定できるようになるまでのつなぎの小技かも。
2001/09/29 リードオンリー Linux 環境
中国に納めた設備がトラぶった。プログラムハング→強制電源OFF→GNOME 起動せず。(汗) GNOME が起動しない原因はセッションが壊れてたらしく、現地技術スタッフの手により [SHIFT]+[CTRL]を押しながらログインで復旧。
プログラムがハングした原因はおそらく Kylix の例外処理バグ(といいつつ大半が自分のバグだったり する(^^;)なので根本解決は Borland 待ち、とりあえず暫定対策。
それとは別に強制電源 OFF 対策をしたい。
手元に資料があるネットワークマウントによるディスクレス環境はこの場合使えない。 たしかワイルドラボの子羊ルータがファイルシステムを リードオンリーマウントして、強制電源 OFF が出来たはず。 これが一番近そうなので、とりあえずリードオンリーマウントしてあとは逐一エラーに対応していく 方針にする。
シングルユーザーモード以外では起動後に mount -r -o remount / はできないようなので、/etc/fstab を変更する
/dev/hda5       /               ext2    defaults        1       1
↓
/dev/hda5       /               ext2    defaults,ro     1       1
再起動。/etc/mtab によるとリードオンリーになっているが、実際はなぜかリードオンリーになって いない。探していくと /etc/rc.d/rc.sysinit 中にルートファイルシステムの再マウントがあるので、 コメントアウトしてみる。 /var/run/... /var/lock/... が書けない、とたくさんエラーを出してくる。 予定通りメモをとりまくる。・・・・・・あっ、止まった。(続く?)
2001/09/30 リードオンリー Linux 環境
(続き)boot:linux 1 でシングルユーザーモードで復旧して、 フルラムディスク Linux を参考にラムディスクを作成して、書き込みエラーのあったディレクトリ /var /tmp /etc を起動時に ramdisk に作って、シンボリックリンクにしてみる。
/#tar czvf tmp.tar.gz tmp
/#tar czvf var.tar.gz var
/#tar czvf etc.tar.gz etc
/#ln -s /mnt/ramdisk/tmp
/#ln -s /mnt/ramdisk/var
/#ln -s /mnt/ramdisk/etc

/etc/rc.d/rc.sysinit を一部書き換え(起動しなくなる)
mke2fs /dev/ram0
mount -t ext2 /dev/ram0 /mnt/ramdisk
tar xzvf /var.tar.gz -C /mnt/ramdisk
tar xzvf /tmp.tar.gz -C /mnt/ramdisk
tar xzvf /etc.tar.gz -C /mnt/ramdisk
起動しなくなった。/etc 自体が /etc/rc.d/rc.sysinit を実行するまで存在していない から当然だった。・・・げげっ、復旧の手段が無い。・・・バックアップから復元中・・・。 /etc は常に存在する必要があるので、/etc をマウントポイントにしてみる。 ルートファイルシステムがリードライト状態なら、一応起動するようになった。 そのかわり、シャットダウンに失敗する、/etc/mtab の整合が取れない、ラムディスクを2つ とっている分メモリの使用効率が悪い。(スワップが起こったら強制電源 OFF が出来ない) 進んでいるんだか後退しているんだか(^^;

問題点は見えてきたので、/etc のマウントについて googleで linux ramdisk etc mount runlevel で検索してみる。 知能工学科のdiskless Linuxに関するメモ を発見、ramdisk に置くファイルはもう少し減らせそうだ、シャットダウンは runlevel 6 で 何か細工すれば出来そうな気がする。あとは時間をかければ何とかなりそうだ。 (=時間が無い)ということでしばらく保留。