2011年4月12日

DelphiでSingletonパターンを実装する(続き)

前回の実装では基本的にinitialization (ja)/finalization (ja)部でインスタンス変数を処理していましたが、この方法だと(T)Singletonを実際には使用していなくてもDelphiのリンカがそれを認識できず、TSingletonのコードを常にリンク対象としてしまう、という問題点があります(それ以上にあんまりオブジェクト指向っぽくない、という点も…)。そこでinitialization/finalization部の処理をDelphi 2010で導入されたクラスコンストラクタ (ja)/クラスデストラクタ (ja)で置き換えて、必要ないコードのリンクが行われないようにしてみます。

まず"シングルトンもどき"です。
unit Unit4;

interface

type
  TSingleton = class(TObject)
  private
    FTestValue: Integer;
  public
    class constructor Create;
    class destructor  Destroy;
    constructor Create;
    destructor  Destroy; override;
    property    TestValue: Integer
                  read  FTestValue
                  write FTestValue;
  end;

function Singleton: TSingleton;


implementation

var
  FSingleton: TSingleton;

function Singleton: TSingleton;
begin

  if FSingleton = nil then
  begin
    FSingleton := TSingleton.Create;
  end;

  Result := FSingleton;

end;

class constructor TSingleton.Create;
begin

  FSingleton := nil;

end;

class destructor TSingleton.Destroy;
begin

  FSingleton.Free;

end;

constructor TSingleton.Create;
begin

  inherited;

  { Initialize }
  FTestValue := 0;

end;

destructor TSingleton.Destroy;
begin

  { Finalize }

  inherited;

end;

end.
次に"本当の"シングルトンです。
unit Unit8;

interface

uses
  SysUtils;

type
  TSingleton = class(TObject)
  private
    FTestValue: Integer;
    class var
      FSingleton: TSingleton;
    constructor CreateInstance;
  public
    class constructor Create;
    class destructor  Destroy;
    constructor Create;
    destructor  Destroy; override;
    class function GetInstance: TSingleton;
    property    TestValue: Integer
                read  FTestValue
                write FTestValue;
  end;

  ECreateSingleton = class(Exception)
  end;


implementation

{ TSingleton }

class constructor TSingleton.Create;
begin

  FSingleton := nil;

end;

class destructor TSingleton.Destroy;
begin

  FSingleton.Free;

end;

constructor TSingleton.Create;
begin

  raise ECreateSingleton.Create('TSingleton.Create cannot use.');

end;

constructor TSingleton.CreateInstance;
begin

  inherited Create;

  { Initialize }
  FTestValue := 0;

end;

destructor TSingleton.Destroy;
begin

  { Finalize }

  inherited;

end;

class function TSingleton.GetInstance: TSingleton;
begin

  if FSingleton = nil then
  begin
    FSingleton := TSingleton.CreateInstance;
  end;

  Result := FSingleton;

end;

end.
CriticalSectionによる排他処理を加えたものです。
unit Unit12;

interface

uses
  SysUtils, Windows;

type
  TSingleton = class(TObject)
  private
    FTestValue: Integer;
    class var
      FSingleton: TSingleton;
      FCriticalSection: TRTLCriticalSection;
    constructor CreateInstance;
  public
    class constructor Create;
    class destructor  Destroy;
    constructor Create;
    destructor  Destroy; override;
    class function GetInstance: TSingleton;
    property    TestValue: Integer
                  read  FTestValue
                  write FTestValue;
  end;

  ECreateSingleton = class(Exception)
  end;


implementation

{ TSingleton }

type
  TInitializeCriticalSectionExFunc = function(var lpCriticalSection: TRTLCriticalSection;
                                              dwSpinCount: DWORD;
                                              Flags: DWORD): BOOL; stdcall;

const
  CRITICAL_SECTION_NO_DEBUG_INFO = $01000000;

class constructor TSingleton.Create;
var
  InitializeCriticalSectionEx: TInitializeCriticalSectionExFunc;
begin

  FSingleton := nil;

  @InitializeCriticalSectionEx := GetProcAddress(GetModuleHandle(kernel32),
                                                 'InitializeCriticalSectionEx');
  if Assigned(InitializeCriticalSectionEx) = True then
  begin
    InitializeCriticalSectionEx(FCriticalSection,0,CRITICAL_SECTION_NO_DEBUG_INFO);
  end
  else
  begin
    InitializeCriticalSectionAndSpinCount(FCriticalSection,0);
  end;

end;

class destructor TSingleton.Destroy;
begin

  DeleteCriticalSection(FCriticalSection);
  FSingleton.Free;

end;

constructor TSingleton.Create;
begin

  raise ECreateSingleton.Create('TSingleton.Create cannot use.');

end;

constructor TSingleton.CreateInstance;
begin

  inherited Create;

  { Initialize }
  FTestValue := 0;

end;

destructor TSingleton.Destroy;
begin

  { Finalize }

  inherited;

end;

class function TSingleton.GetInstance: TSingleton;
begin

  EnterCriticalSection(FCriticalSection);
  try
    if FSingleton = nil then
    begin
      FSingleton := TSingleton.CreateInstance;
    end;

  finally
    LeaveCriticalSection(FCriticalSection);
  end;

  Result := FSingleton;

end;

end.
最後に事前初期化版です。
unit Unit16;

interface

uses
  SysUtils, Windows;

type
  TSingleton = class(TObject)
  private
    FTestValue: Integer;
    class var
      FSingleton: TSingleton;
    constructor CreateInstance;
  public
    class constructor Create;
    class destructor  Destroy;
    constructor Create;
    destructor  Destroy; override;
    class function GetInstance: TSingleton;
    property    TestValue: Integer
                  read  FTestValue
                  write FTestValue;
  end;

  ECreateSingleton = class(Exception)
  end;


implementation

{ TSingleton }

class constructor TSingleton.Create;
begin

  FSingleton := TSingleton.CreateInstance;

end;

class destructor TSingleton.Destroy;
begin

  FSingleton.Free;

end;

constructor TSingleton.Create;
begin

  raise ECreateSingleton.Create('TSingleton.Create cannot use.');

end;

constructor TSingleton.CreateInstance;
begin

  inherited Create;

  { Initialize }
  FTestValue := 0;

end;

destructor TSingleton.Destroy;
begin

  { Finalize }

  inherited;

end;

class function TSingleton.GetInstance: TSingleton;
begin

  Result := FSingleton;

end;

end.
プロジェクト内でTSingletonを使用していない場合、TSingleton関係のコードがリンクされないことがわかります。

TMS Smooth Controls for Delphi and C++Builder XE

まだ正式なアナウンスはありませんが、RADStudio/Delphi/C++Builder XEの登録ユーザ向にTMS SoftwareのTMS Smooth Controls for Delphi and C++Builder XEがCodeCentralからダウンロードできるようになっています。

28271 TMS Smooth Controls for Delphi and C++Builder XE

どうやらUSで始まったGet RAD Studio XE at the Delphi/C++Builder Price!というキャンペーンの一環でPlus bonus TMS Smooth Controls Pack at no extra chargeということのようです。日本ではどうなるのでしょうか。高橋さん、情報ありがとうございます。

2011/06/01追記: 登録ユーザダウンロードに表示されているのでいまさらのような気がしますが、日本でもキャンペーンが始まったようです。

Team Japan » 「TMS Smooth Controls Pack for Delphi XE and C++Builder XE」を入手しよう
強力なビジュアル開発ツールスイート「RAD Studio XE」にアップグレードしよう!

2011年4月11日

DelphiでSingletonパターンを実装する

GoFによるデザインパターンシングルトンパターンをDelphiで実装することを考えてみます。シングルトンパターン(Singleton pattern)とは、
あるクラスに対してインスタンスが1つしか存在しないことを保証し、それにアクセスするためのグローバルな方法を提供する。
ことを目的とした"生成に関するパターン"の一つです。

最初に"シングルトンもどき"です。Delphiプログラマがシングルトンと聞くと、Printerオブジェクト(Printers.Printer (ja))を思い浮かべることが多いのではないでしょうか。Printerは厳密な意味でのシングルトンではありませんが、実用上はこの程度の実装で十分なことが多いのも確かです。この"シングルトンもどき"("Printerパターン"?)は、唯一となるべきインスタンスを格納する変数を隠蔽して、代わりにインスタンスを返す関数を用意しておき、最初のアクセスでインスタンスを生成する、というやりかたで、実際には複数のインスタンスを生成することが可能なのですが、逆にグローバルなインスタンスは一つでも、ローカル/一時的なインスタンスはそれとは別に生成したい、というような場合にはとても適合しています。
unit Unit2;

interface

type
  TSingleton = class(TObject)
  private
    FTestValue: Integer;
  public
    constructor Create;
    destructor  Destroy; override;
    property    TestValue: Integer
                  read  FTestValue
                  write FTestValue;
  end;

function Singleton: TSingleton;


implementation

var
  FSingleton: TSingleton;

function Singleton: TSingleton;
begin

  if FSingleton = nil then
  begin
    FSingleton := TSingleton.Create;
  end;

  Result := FSingleton;

end;

constructor TSingleton.Create;
begin

  inherited;

  { Initialize }
  FTestValue := 0;

end;

destructor TSingleton.Destroy;
begin

  { Finalize }

  inherited;

end;

initialization
  FSingleton := nil;

finalization
  FSingleton.Free;

end.
Singleton関数を通してグローバルな唯一のインスタンスを取得することができ、必要に応じてコンストラクタを呼び出すことでローカル/一時的なインスタンスを生成することもできます。

次に"本当の"シングルトンを考えてみます。ただしDelphiでは、全てのクラスがpublicなconstructor Create (ja)を持つTObject (ja)から派生しており、かつメンバ関数のスコープを狭めることができないという言語仕様から、C++やJavaのように通常のコンストラクタ呼び出しをコンパイルエラーにすることができません。そこで次善の策としてpublicなコンストラクタを呼び出すと例外がraiseされ、インスタンスの生成に失敗するようにしてみました。
unit Unit6;

interface

uses
  SysUtils;

type
  TSingleton = class(TObject)
  private
    FTestValue: Integer;
    constructor CreateInstance;
  public
    constructor Create;
    destructor  Destroy; override;
    class function GetInstance: TSingleton;
    property    TestValue: Integer
                  read  FTestValue
                  write FTestValue;
  end;

  ECreateSingleton = class(Exception)
  end;


implementation

var
  FSingleton: TSingleton;

{ TSingleton }

constructor TSingleton.Create;
begin

  raise ECreateSingleton.Create('TSingleton.Create cannot use.');

end;

constructor TSingleton.CreateInstance;
begin

  inherited Create;

  { Initialize }
  FTestValue := 0;

end;

destructor TSingleton.Destroy;
begin

  { Finalize }

  inherited;

end;

class function TSingleton.GetInstance: TSingleton;
begin

  if FSingleton = nil then
  begin
    FSingleton := TSingleton.CreateInstance;
  end;

  Result := FSingleton;

end;

initialization
  FSingleton := nil;

finalization
  FSingleton.Free;

end.
TSingleton.GetInstanceを呼び出すことでTSingletonの唯一のインスタンスにアクセスすることができます。

しかしよく指摘されるように、これらの実装には、マルチスレッドになっているプログラム上で別々のスレッドから競合するタイミングでTSingleton.GetInstanceを呼び出すとインスタンスが多重に生成される可能性がある、という問題が存在しています。これを避けるためにCriticalSectionで排他をかけてみます。なおWindows Vista以降ではクリティカルセクション構造体をInitializeCriticalSectionで初期化するとリソースリークし、一方でWindows 2000ではInitializeCriticalSectionで初期化すると残りメモリが逼迫したときにEnterCriticalSectionで例外が発生するという問題があるので、可能であればInitializeCriticalSectionExを、それ以外ではInitializeCriticalSectionAndSpinCount (ja)を呼び出すようにしています。
unit Unit10;

interface

uses
  SysUtils, Windows;

type
  TSingleton = class(TObject)
  private
    FTestValue: Integer;
    constructor CreateInstance;
  public
    constructor Create;
    destructor  Destroy; override;
    class function GetInstance: TSingleton;
    property    TestValue: Integer
                  read  FTestValue
                  write FTestValue;
  end;

  ECreateSingleton = class(Exception)
  end;


implementation

var
  FSingleton: TSingleton;
  FCriticalSection: TRTLCriticalSection;

{ TSingleton }

constructor TSingleton.Create;
begin

  raise ECreateSingleton.Create('TSingleton.Create cannot use.');

end;

constructor TSingleton.CreateInstance;
begin

  inherited Create;

  { Initialize }
  FTestValue := 0;

end;

destructor TSingleton.Destroy;
begin

  { Finalize }

  inherited;

end;

class function TSingleton.GetInstance: TSingleton;
begin

  EnterCriticalSection(FCriticalSection);
  try
    if FSingleton = nil then
    begin
      FSingleton := TSingleton.CreateInstance;
    end;

  finally
    LeaveCriticalSection(FCriticalSection);
  end;

  Result := FSingleton;

end;

type
  TInitializeCriticalSectionExFunc = function(var lpCriticalSection: TRTLCriticalSection;
                                              dwSpinCount: DWORD;
                                              Flags: DWORD): BOOL; stdcall;

const
  CRITICAL_SECTION_NO_DEBUG_INFO = $01000000;

procedure InitializeSingleton;
var
  InitializeCriticalSectionEx: TInitializeCriticalSectionExFunc;
begin

  FSingleton := nil;

  @InitializeCriticalSectionEx := GetProcAddress(GetModuleHandle(kernel32),
                                                 'InitializeCriticalSectionEx');
  if Assigned(InitializeCriticalSectionEx) = True then
  begin
    InitializeCriticalSectionEx(FCriticalSection,0,CRITICAL_SECTION_NO_DEBUG_INFO);
  end
  else
  begin
    InitializeCriticalSectionAndSpinCount(FCriticalSection,0);
  end;

end;

initialization
  InitializeSingleton;

finalization
  DeleteCriticalSection(FCriticalSection);
  FSingleton.Free;

end.
上記の例と同様にTSingleton.GetInstanceでTSingletonの唯一のインスタンスにアクセスすることができますが、GetInstanceを呼び出す毎にEnterCriticalSection/LeaveCriticalSectionするため、一旦インスタンスが生成された後でも本質的に必要のないオーバヘッドが存在しています。

排他処理のコストを無視することができない場合は、通常のシングルトンパターンの実装の長所の一つである"インスタンスの生成を必要になるまで遅延する"を捨てて、インスタンスをアプリケーションの初期化時に生成してしまう、という方法もあります。
unit Unit14;

interface

uses
  SysUtils;

type
  TSingleton = class(TObject)
  private
    FTestValue: Integer;
    constructor CreateInstance;
  public
    constructor Create;
    destructor  Destroy; override;
    class function GetInstance: TSingleton;
    property    TestValue: Integer
                  read  FTestValue
                  write FTestValue;
  end;

  ECreateSingleton = class(Exception)
  end;


implementation

var
  FSingleton: TSingleton;

{ TSingleton }

constructor TSingleton.Create;
begin

  raise ECreateSingleton.Create('TSingleton.Create cannot use.');

end;

constructor TSingleton.CreateInstance;
begin

  inherited Create;

  { Initialize }
  FTestValue := 0;

end;

destructor TSingleton.Destroy;
begin

  { Finalize }

  inherited;

end;

class function TSingleton.GetInstance: TSingleton;
begin

  Result := FSingleton;

end;

initialization
  FSingleton := TSingleton.CreateInstance;

finalization
  FSingleton.Free;

end.
現実のアプリケーションでは常にトレードオフが存在しますので、必要に応じてこれらのいずれかの(あるいはこれ以外でも)実装を選択する、ということになります。なお"これらのシングルトンに必要な実装を行った基底クラス"と"実際に使用するシングルトンの派生クラス"、というアプローチは(個人的には)いろんな意味で望ましいとは思えません。

元ねたはオブジェクト指向における再利用のためのデザインパターン(改訂版) (amazon) (Erich Gamma、Richard Helm、Ralph Johnson、John M. Vlissides著/本位田 真一、吉田 和樹監訳/ソフトバンククリエイティブ/ISBN4-7973-1112-6(ISBN978-4797311129)/5,040円)とHead Firstデザインパターン (amazon) (Eric Freeman、Elisabeth Freeman、Kathy Sierra、Bert Bates著/木下 哲也、有限会社 福龍興業訳/佐藤 直生監訳/ISBN4-87311-249-4/4,830円)。

2011年4月8日

[書籍]Delphi in Depth: ClientDataSets

CreateSpaceで注文した

Delphi in Depth: ClientDataSets (CreateSpace, amazon US)/Cary Jensen著/CreateSpace/ISBN 978-1461008583/44.99USD

が配送されてきました(2011/04/01に注文、Shippingの7.38USDを加えて52.37USD=4,537JPY(暫定値)4,450JPY(1USD=84.973JPY))。

元ねたはCary Jensen "Let's Get Technical": Delphi in Depth: ClientDataSets

2011/04/14追記: 日本のAmazonでも扱いが始まったようです。4,795円ですので、CreateSpaceで買うのとあまり変わりませんね。

Amazon.co.jp: Delphi in Depth: Clientdatasets: Cary, Ph.d. Jensen: 洋書

元ねたはOldTPFunさんのtweet

2011/04/28追記: カードの利用明細によると4,450円で決済された模様(円高ですね)。と、確認してみたらamazon.co.jpでの扱いが止まっているようです。Shippingを加えてもCreateSpaceで買ったほうがいいようですね。

2011年4月5日

Delphi 64bitコンパイラスニークプレビュー

64bitコンパイラのスニークプレビューとベータプログラムがアナウンスされています。

Delphi 64-bit コンパイラ・スニークプレビュー (EDN/ja)
Delphi 64-bit Compiler Sneak Preview (日本語情報、プレビュービデオに日本語字幕付き)

Delphi 64-bit Compiler Sneak Preview (EDN/en)
Delphi 64-bit Compiler Sneak Preview
Delphi Insider: Delphi 64-bit Compiler Sneak Preview and Beta - Official Announcement
Delphi 64-bit Compiler Preview and Beta Program | Andreano Lanusse Blog | Technology and Software Development

スニークプレビューは先日のデベロッパーキャンプのT1セッションのものとほぼ同一(素材はおそらく前日の韓国向けのもの)でした。ベータプログラムはRAD Studio/Delphi XEユーザを優先、という話は64-bit版Delphiフィールドテストのご案内にもあるとおりです。

プレビュービデオを見ていて、呼出規約が原則として単一になる、というところで、safecall (ja)は依然として特別扱いになる(safecall is still "special")、という一文があることに気付きました。safecallとはヘルプにsafecall 規約は、例外 'firewalls' を実装しています。 Win32 では、これがプロセス間の COM エラー通知を実装しています。とあるようにCOMインタフェースにおける例外保護を追加したものになります(Wikipediaにも解説がありますね)。

RAD Studio/Delphi/C++Builder XE付属のFinalBuilderのアップデート

RAD Studio/Delphi/C++Builder XEにバンドルされているFinalBuilderがアップデートされ、FinalBuilder Embarcadero Edition(Ent/Arc SKUのみ)が7.0.0.1105になっています。

FinalBuilder Update for RAD Studio XE, Delphi XE and C++Builder XE
RAD Studio XE, Delphi XE, C++Builder XE向け FinalBuilder アップデート
28278 FinalBuilder for Delphi, C++Builder and RAD Studio XE

FinalBuilder 7 Version History

2011年4月1日

Pulsarフィールドテスト

先日のデベロッパーキャンプのときにも話に出ていた次期版Delphi(Pulsar)のフィールドテスタ募集のお知らせです。

64-bit版Delphiフィールドテストのご案内

今回は「品質向上のためのフィードバックを目的としたフィールドテスト」(今回募集)と「新バージョンに向けての動作検証や開発準備を目的としたフィールドテスト」(後日募集予定)に(時期や目的を)分けて行うようです。64bit版Delphiが欲しくて仕方がなかった人は積極的に参加してみてはいかがでしょう。

2011/04開催のウェブセミナー

2011/04/14 15:00-16:00(JST) 次世代ToolCloud - AppWaveによるアプリケーション配布の管理
2011/04/19 17:00-18:00(JST) 次世代ToolCloud - AppWaveによるアプリケーション配布の管理
2011/04/21 17:00-18:00(JST) データベース開発者のためのDB PowerStudio入門
2011/04/27 17:00-18:00(JST) DB PowerStudioで実現するデータベース管理の効率化

2011年3月30日

第19回エンバカデロ・デベロッパーキャンプ開催

今日は10:00開始予定ですが、事前の予告どおりセッション資料がダウンロードできるようになっています(参加確認のメールにURLが記載されています)。午後からはUDXに行く予定です。

まもなく始まりますね。
あら、Allenさんは不参加ですか(G2もDavid Iさんが担当)。残念ですね。G1が始まりました。

【G1】ジェネラルセッション「エンバカデロ - 2011年の製品戦略と最新情報 ~ ToolCloudのさらなる進化へ」
  • 去年から使っているXEというブランディングはクロスプラットフォーム、ToolCloud対応を意味している。
  • 最近qadramとksdevを買収した。qadramはRadPHP、ksdevはグラフィック関係。
  • 2011-2012年にフォーカスする項目としては64bit(x64)、Cross-Platform(MacOS/Linux)、Community 3.0(EDNのソーシャル化)、VCL+(VCLの強化)、DataSnap Serverの進化、Modular Compiler Architecture(モジュール化の導入)、Mobile Connectivity(モバイル端末をDataSnapに接続)、PadPHPの次世代版。
  • 次世代版ToolCloudにアプリケーションを組み込むことでSxS、インストールレス、ライセンス管理を実現できる。Discovery、Immidiacy、Permanence、Convenience。AppWave経由で配布する。

【G2】テクノロジープレビュー「64bitコンパイラへの道~Delphi/C++Builderの将来バージョンへ」
  • 64bit Delphiとは何を意味するのか。
  • Integer、Longint、Cardinal、Int64、UInt64のような整数型、UnicodeString、AnsiString、WideStringのような文字列型、例外、RTL、VCLのインタフェースなどは変更されない。
  • NativeInt、NativeUInt(いずれも32bit/64bit)、Pointer(StringやInterfaceなどPointer的に振る舞うものを含む)(32bit/64bit)、動的配列(インデックスが64bit化)、実数型(Doubleのみ)には違いがある。
  • 64bit版ではWIN64、CPUX64が定義され、WIN32、CPU386、CPUX86が未定義になる。
  • 注意すべき点: SizeOf(Pointer) <> SizeOf(Integer)であること、DLLなどを含めx64版でそろえる必要があること、呼び出し規約は1つしかない(指定しても無視)、pointer math、インラインアセンブラでasmとpascelをミックスできないなど制約あり(田川さんからdcc64 は最外側のasmブロックをサポートしますが、行単位asmはサポートしません。Dcc64 supports BASM. However, it only supports outermost asm-block, not asm-statement....今の予定では。...That's the plan for the present time.とのフォローあり)、SetWindowLong/GetWindowsLongではなくSetWindowLongPtr/GetWindowsLongPtrを使うべき(SetWindowLongはSetWindowLongPtrにマップされる)。
  • メッセージ関係ではWPARAM/LPARAMは明示的にキャストする、resultはLRESULTにキャスト、message crackerの構造体は変更されている、という点に注意。
  • インラインアセンブラは移植性のためPascalに置き換えを推奨
  • x64に対応するときはプロジェクトのTarget PlatformsにWindows (64-bit)を追加する。
  • ツールベンダ、コンポーネントベンダには32/64bit両対応を働きかけている。
  • x64ではシステム的に浮動小数点数の扱いが64bit(Double)に統一されているが、RTLでSingle(32bit)、Extended(80bit)をサポートすることも検討している。
  • ToolCloud対応はアプリケーションのマスタリング処理で必要なことを行うため、基本的にアプリケーション側で特別に対応する必要はない。特定のハードウェア(マルチタッチなど)を前提とする場合は注意。
  • 64bit版は既にベータプログラムが始まっているので、x64対応を考えているベンダは日本法人(藤井さん)にコンタクト(インフォメーションサービスセンターあてでOK)をとってほしい。ベータテストは現在はコンパイラ中心で進んでいて、製品全体としてはもう少し後になる。
  • 例年どおりのリリーススケジュールを期待している(意訳すると9月目標ですか)。

さて、秋葉原に移動します。午後はUStream中継もありとのこと。

GoToWebinarはなかなかいいですね。

会場到着。20人くらいでしょうか。

【T3】 Delphiテクニカルセッション「Delphi IDEでTwitter生活!Open Tools APIで開発環境を簡単カスタマイズ」
【T4】 C++Builderテクニカルセッション「C++BuilderによるWebサービス&マルチスレッド対応リソースプールの設計」
T3/T4/T5/T6セッションに加えてG1/G2セッションの資料もダウンロードできるようになっています。

【T5】 Delphi/C++Builderテクニカルセッション「バグを生まないための開発技法 - テストと例外の使い方」
  • テストは大事。テストすべき想定状況も大事。
  • DUnitはテストをシステマチックに行うためのフレームワーク。
  • 構造化例外の件は…まぁ人により好き嫌いがありますからね。

【T6】 PHPテクニカルセッション「PHP Live! - ゼロから始めるPHPアプリの構築からデプロイまで」
無事終了。セッションスピーカ、参加者、関係者のみなさま、お疲れさまでした。

延長戦(単なる飲み会ともいう)も無事終了。コンパイラチームの田川さんから色々なお話を聞けて非常にためになりました。長々とお付き合いいただきありがとうございました。

2011/04/01追記: T3セッションのフォローとしてC++Builder好きの秘密基地さんのリンクを、T4セッションのフォローとしてTeam Japanのアーティクルのリンクを追加。

2011/04/06追記: セッション資料がダウンロードできるようになっています。

第19回 エンバカデロ・デベロッパーキャンプ - セッション資料ダウンロード

また筑木さんのT3セッションのサンプルコードが第19回 エンバカデロ・デベロッパーキャンプ セッションT3自己フォロー - C++Builder好きの秘密基地からダウンロードできるようになっています。

2011/04/08追記: 山本さんのT5セッションのサンプルコードがダウンロードできるようになっています。

DelFusaBlog AccessIniFileとErrorList

2011年3月25日

GpProfile 2011

以前Primoz GabrijelcicさんによるGpProfileというDelphi 2-5用のプロファイラがありました(いまでもありますが)。このGpProfileをAnton AlisovさんがDelphi 2009/2010/XEに対応させたものをGoogle Code上のオープンソースプロジェクトとして公開しています。興味深い。とりあえずメモ。

The Delphi Geek: GpProfile on Google code
gpprofile2011 - GpProfile is a powerful source code instrumenting profiler for all versions of Delphi (including Delphi XE) - Google Project Hosting

2011年3月24日

[書籍]C/C++プログラミングの「迷信」と「誤解」

啓文堂書店の渋谷店

C/C++プログラミングの「迷信」と「誤解」 (amazon)/高木信尚著/技術評論社/ISBN 978-4-7741-4587-7/2,604円

を購入。

第19回エンバカデロ・デベロッパーキャンプは縮小して開催

既に公式サイトでも告知されていますが、第19回エンバカデロ・デベロッパーキャンプは2011年03月30日に規模を縮小して開催されることになりました。具体的には
  • Allen Bauerさんはオンラインでの参加になる
  • オンラインでの中継(今回からLiveMeetingではなくなる模様)に合わせて終日1トラックになる
  • 秋葉原UDXでの参加も可能
といったところです。オンラインで参加の場合は改めて申し込みが必要とのことです。

2011年3月23日

Delphi IDEを拡張する

TMS softwareBruno FierensさんによるOpen Tools API (OTA)を使用したDelphi IDEの拡張に関するホワイトペーパ(英語)が公開されています。

Delphi IDE を拡張する

また関連してBruno FierensさんによるWebinar(こちらも英語)が2011/04/06に予定されています。

Webinar: Creating IDE Extensions with the Delphi Open Tools API

日本時間ベースだと
  • 2011/04/06 22:00(JST) = 2011/04/06 06:00 AM(PDT)
  • 2011/04/07 03:00(JST) = 2011/04/06 11:00 AM(PDT)
  • 2011/04/07 09:00(JST) = 2011/04/06 05:00 PM(PDT)
になります。

2011年3月22日

Delphi IDE Theme Editor

RRUZ(Rodrigo Ruz)さんがDelphi IDEのテーマエディタをリリースしています。興味深い。

Is Your Delphi IDE Hot or Not? – Introducing the Delphi IDE Theme Editor « The Road to Delphi – a Blog About Delphi Programming (mostly)
Delphi IDE Theme Editor – New features « The Road to Delphi – a Blog About Delphi Programming (mostly)
Delphi IDE Theme Editor « The Road to Delphi – a Blog About Delphi Programming (mostly)

Delphi 7以降で使用でき、Visual Studio(2003以降)のテーマ(.vssettings)やEclipseのテーマ(Eclipse Color Theme Plugin)をインポートすることができます。

2011/03/23追記: OldTPFunさんのtweetでしょう、きっと>だれとなく。

2011年3月18日

2011年3月17日

[書籍]俺のコードのどこが悪い?

MARUZEN&ジュンク堂書店 渋谷店(営業時間短縮中)で

俺のコードのどこが悪い? ――コードレビューを攻略する40のルール (amazon)/藤原克則著/秀和システム/ISBN 978-4-7980-2918-4/2,100円

を購入。

2011/03/18追記: 著者の方のblogでも突っ込みが入っていますが、C/C++では規格で条件の評価を左から右に結果が確定するまで行う(短絡評価)とされています。Delphiでもデフォルトでは短絡評価を行いますが、コンパイラ指令{$B+}またはコンパイラオプションで完全評価とすることもできます。

式(Delphi)2.3 完全論理評価と短絡論理評価
論理式のショートサーキット評価(Delphi コンパイラ指令) - RAD Studio

ちなみに.NETではないVisual Basicは完全評価でした。

RAD Studio/Delphi/C++Builder XE Help Update 2

予告されていたRAD Studio/Delphi/C++Builder XEのHelp Update 2がリリースされています。

Delphi XE および C++Builder XE 向け Help Update 2
28256 Help Update 2 for Delphi XE and C++Builder XE

元ねたはTeam Japan » Delphi XE, C++Builder XE, RAD Studio XE向けの「ヘルプアップデート2」

2011/03/28追記: EDNの記事のリンクを追加。

Firebird 3の初期レビュー

Firebird ProjectのリードアーキテクトのDmitry YemanovさんによるFirebird 3の初期レビューのスライドショーが公開されています。

Initial review of Firebird 3

Firebird 3で実装したいと考えられている機能がいろいろと挙げられています。またリリーススケジュールについても言及されています。
  • 2.0.7 - 2011年のQ2-Q3
  • 2.1.5 - 2012年
  • 2.5.1 - 2011年のQ2
  • 3.0 Alpha - 2011年のQ3


元ねたはFirebird News » Initial review of Firebird 3 – Presentation

2011年3月16日

2011年3月14日

更新が減ります

状況が安定していないため、当面の間更新が減ります。ニュース的なものはおそらくお伝えしていきますが、Tips的なものはしばらくお休みになると思います。

2011年3月11日

地震

とりあえず周囲では人的被害はありませんが、岩手県、宮城県、福島県、茨城県方面は大変なことになっているようです。

22:35 帰宅なう。23kmに4時間。そして帰ったとたんにTVのテロップに京王線復旧の情報ががが。

2011年3月10日

RAD Studio/Delphi/C++Builder XE Help Update 2準備中

Dee EllingさんによるとRAD Studio/Delphi/C++Builder XE Help Update 2が近日中にリリースされるようです。Help Update 2における変更点は

Readme - Help Update 2 for Delphi and C++Builder XE - RAD Studio
リリース ノート: Delphi XE および C++Builder XE Help Update 2 - RAD Studio

で確認することができます(日本語版は準備中)

元ねたは公式フォーラムのEmbarcadero Discussion Forums: XE Help Update 2 Sneak Peek

2011/03/16追記: 日本語版のリリースノートのリンクを追加しました。

2011年3月9日

Microsoft Monthly Update 2011/03

今日はMicrosoftのセキュリティアップデートの日です。
MS11-015
MS11-016
MS11-017

2011年3月8日

IInterfaceをTObjectにキャストする

Delphi 2010以降ではIInterfaceからasで任意のクラスにキャストすることが可能になりましたが、それ以前のバージョンでIInterfaceからTObjectにキャストを行う方法についてのBarry KellyさんHallvard Vassbotnさんによる記事。興味深い。とりあえずメモ。

Entropy Overload: An ugly alternative to interface to object casting
Hallvard's Blog: Hack #7: Interface to Object [in The Delphi Magazine]

どちらの記事のコードも基本的には同じで、IInterfaceからvtable(仮想メソッドテーブル)を参照し、最初のエントリにあるスタブメソッドのコードの中にあるオフセットを取得してIInterface(これは実際にはポインタ)に加算することでインスタンスのアドレスを取得する、というハックになっています。

2011年3月5日

RAD Studio/Delphi/C++Builder XE Hotfix

RAD Studio/Delphi/C++Builder XEのHotfixがリリースされています。

Delphi XE, C++Builder XE, RAD Studio XE 向けHotfix

ひとつはInterBase/Firebird DBXドライバがftMemoのフィールドを2回読むとAVになる問題への対応で、Pro SKUとEnt/Arc SKUで別のHotfixになっています。

28249 RAD Studio XE Hotfix for RAID 280988 (QC 89242) - Pro
28248 RAD Studio XE Hotfix for RAID 280988 (QC 89242) - Arch and Ent

もうひとつはTClientDataSetとTProviderの組み合わせでデータベースサーバからマイナス値のステータスコードを受け取るとエラーになる問題の対応で、こちらはEnt/Arc SKUのみPro/Ent/Arc SKU共通です。

28247 RAD Studio XE Hotfix for RAID 280864 (QC 88928)

2011/03/06追記: EDNの日本語版の記事が出たのでリンクを差し替えました。週末なのにご苦労さまです。

2011/03/27追記: Team Japan

Team Japan » RAD Studio XE Hotfix for QC 88928は、Pro版にも適用可能です

によるとQC 88928のHotfix(28247)はPro SKUにも適用する必要があるとのことです。

2011年2月25日

Windowsにおける呼出規約の歴史

Raymond ChenさんのThe Old New ThingにWindowsにおける呼出規約(Calling Convention)とその歴史的経緯に関するアーティクルがありました。

The history of calling conventions, part 1 - The Old New Thing - Site Home - MSDN Blogs
Part 1では16bit環境での規約(C/Pascal/Fortran/Fastcall)について説明しています。16bit環境ではどの規約でもBP、SI、DIの内容は保持される必要があり、戻値はAX(16bit)またはDX:AX(32bit)に格納します。

The history of calling conventions, part 2 - The Old New Thing - Site Home - MSDN Blogs
Part 2では過去に存在した32bitのx86以外のCPU(Alpha AXP/MIPS R4000/PowerPC)の規約について説明しています。これらのCPUでは呼出規約が1つずつしかありません。またRISC系CPUでレジスタが多く存在するため、スタックをなるべく使わないようになっています。

The history of calling conventions, part 3 - The Old New Thing - Site Home - MSDN Blogs
Part 3ではx86(32bit)の規約(C/__stdcall/__fastcall/thiscall)について説明しています(Microsoftのものだけですが)。どの規約でもEDI、ESI、EBP、EBXの内容は保持される必要があり、EDX:EAXレジスタペアに戻値を格納します。なおC++のメンバ関数ではthisポインタが暗黙の第1パラメータとなることに注意が必要です。またWin32APIは基本的に__stdcallです。(参考: Results of Calling Example)

The history of calling conventions, part 4: ia64 - The Old New Thing - Site Home - MSDN Blogs
Part 4ではia64(Intel Itanium)の規約について説明しています。ia64には呼出規約は1つしかありません。ia64には128のレジスタがあり、グローバルに使用する32(r0-r31)を除いたローカル領域の96(r32-r127)について、関数はレジスタをいくつローカル/パラメータで使用するのかを宣言するようになっており、可能であればレジスタ間のシフト(実際にはレジスタリネーミングでしょう)で、もし必要であれば専用のレジスタスタックを使用するようになっています(解釈が違ったらすいません)。戻値はグローバル領域のレジスタ経由で呼び出し元に返され、リターンアドレスも通常はローカル領域のレジスタ上に置かれます。興味深いのはスタック上の最初の16バイトは誰がいつどのように使ってもいい(=関数を呼び出したら内容が破壊されているかもしれない)領域となっていることと、ia64上の関数ポインタは関数のエントリポイントではなく関数記述構造体(a structure that describes the function)を指しており、構造体の前半8バイトがエントリポイント、次の8バイトが"gpレジスタ"の値を格納するようになっているということでしょうか(関数ポインタがエントリポイントではなくある種の構造体を指すというのはRISC系CPUと共通しています)。

The history of calling conventions, part 5: amd64 - The Old New Thing - Site Home - MSDN Blogs
Part 5ではx64(AMD64)の規約について説明しています。
てきとうな要約:
  • x64ではx86のレジスタが64bitに拡張されており(RAX、RBX、...)、さらにR8-R15の8つのレジスタが追加されています。
  • x64についても呼出規約は1つしかありません。
  • 最初の4つのパラメータはRCX、RDX、R8、R9に格納され、それ以降はスタックに配置されますが、スタック上には最初の4つのパラメータの分の領域も確保されます。
  • パラメータが64bit未満の場合、上位ビットを0にするのではなくごみ("garbage")のままとなり、64bitよりも大きいパラメータはその格納アドレスが渡されます。
  • 戻値はRAXに格納されますが、64bitよりも大きい場合は第1パラメータとして戻値を格納する領域のアドレスが渡されます。
  • RAX、RCX、RDX、R8、R9、R10、R11以外のレジスタの内容は保持される必要があります。
  • スタックのクリーンアップは呼出元の責任です。
  • スタックは16バイトアライメントで維持されます。

Delphi(x86)の呼出規約については

Procedures and Functions (Delphi) - RAD Studio
プロシージャと関数 - RAD Studio

に説明があります。またx64については日本語だとAkihiro NotesさんMicrosoft x64 呼び出し規約の説明がわかりやすいですね。

2011年2月23日

x64プログラミングの参考資料

次期版のDelphi "Pulsar"では従来の32bit版Windows(x86)に加えて64bit版Windows(x64)とMacOS X(x86)のサポートが追加される予定です。Windows x64に関しては既にMicrosoftのVisual Studio (Visual C++)がサポートしていますが、Microsoftによるx64プログラミングの解説がMSDNにありました。

x64 の入門書: 64 ビット Windows システムのプログラミングを開始するときに必要な知識 -- MSDN Magazine, 2006 年 5 月
Visual C++ による 64 ビット プログラミング
64 ビット Windows プログラミング ガイド (Windows)

x86とx64の大きな違いは
  • データサイズ(32/64bit)
  • 呼出規約(calling convention)
  • 例外処理(SEH)
でしょうか(細かい話ではPE32+ヘッダやprintfの書式指定などもありますが)。これらの記事は"Pulsar"でも十分に役立つと思います。

2011年2月22日

64bit版Windowsでシステムキャッシュが物理メモリを使い切ってしまう現象

Firebird News

Firebird slow? Well, maybe it is Windows fault.

という記事がありました。FirebirdをWindows x64(XP/Server 2003/Vista/Server 2008)で動作させると処理がスローダウンする場合があり、

You experience performance issues in applications and services when the system file cache consumes most of the physical RAM
Too Much Cache? - Ntdebugging Blog - Site Home - MSDN Blogs

にあるようにシステムキャッシュが物理メモリを使い切ってしまう(物理メモリの最大90%をシステムが占有してしまい、残りの10%の物理メモリしかアプリケーションで使用できない)現象が存在する、という話です(原因はFirebirdとは全く無関係)。日本語だと

リソース不足について – 番外編1 (64bit 環境での注意点) - Ask CORE - Site Home - TechNet Blogs

あたりが詳しいのですが、対策としてはアプリケーション側からGetSystemFileCacheSize/SetSystemFileCacheSizeを使用してワーキングセットの上限値を制限する必要があります。またこれをサービスとして制御する

Microsoft Windows Dynamic Cache Service

というものを利用する方法もあります(むしろこちらが本命)。

なおWindows 7/Server 2008R2ではメモリ管理関係が設計から見直されていてこの問題は存在しないとのことです。

2011年2月21日

TFileStreamのコンストラクタで指定するアクセスモードについて

Delphiでファイルを扱うときによく使うTFileStream (ja)のコンストラクタCreate (ja)の第2パラメータModeと、WindowsのAPIであるCreateFile (ja)の第2パラメータdwDesiredAccess、第3パラメータdwShareMode、第5パラメータdwCreationDispositionの関係を調べてみました。

まずModeに指定できる値としてfm...の定義値を調べてみます。fmCreateのみがClasses.pasに
  fmCreate = $FFFF;
(Classes.pasの53行目)(Delphi 2007の場合、以下同じ)

と定義され、その他の値はSysUtils.pasに
  fmOpenRead       = $0000;
  fmOpenWrite      = $0001;
  fmOpenReadWrite  = $0002;

  fmShareCompat    = $0000 platform; // DOS compatibility mode is not portable
  fmShareExclusive = $0010;
  fmShareDenyWrite = $0020;
  fmShareDenyRead  = $0030 platform; // write-only not supported on all platforms
  fmShareDenyNone  = $0040;
(SysUtils.pasの44行目付近)

と定義されています。…fmCreateが0xFFFFで他の定義値が16bitの定数ということは、ModeにfmCreateを指定した場合、その他の指定は一切意味を持たない、ということになりますね。実際にTFileStream.Createを見てみると、
constructor TFileStream.Create(const AFileName: string; Mode: Word; Rights: Cardinal);
  begin
  if Mode = fmCreate then
  begin
  ...
  end
  else
  begin
  ...
  end;
  FFileName := AFileName;
end;
(Classes.pasの5474行目付近)

と、確かにModeがfmCreateかそれ以外かで完全に処理が分けられてしまっています。ではfmCreateのケースをさらに追ってみます。
inherited Create(FileCreate(AFileName, Rights));
(Classes.pasの5478行目)

とSysUtils.pas上のFileCreate (ja)を呼び出しています(inherited CreateはTFileStreamの派生元であるTHandleStream (ja)のコンストラクタ呼び出しです)。FileCreateは
Result := Integer(CreateFile(PChar(FileName), GENERIC_READ or GENERIC_WRITE,
    0, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0));
(SysUtils.pasの5259行目付近)

という実装であり、結果としてfmCreateの場合、dwDesiredAccessはGENERIC_READ or GENERIC_WRITE、dwShareModeは0(Prevents other processes from opening a file or device if they request delete, read, or write access.=他の処理からは削除、読み込み、書き込みアクセスできない)、dwCreationDispositionはCREATE_ALWAYS(新しいファイルを作成します。指定したファイルが既に存在している場合、そのファイルを上書きし、既存の属性を消去します。)と、これらの値が固定的に指定される、ということになります。

一方fmOpen...の場合、
inherited Create(FileOpen(AFileName, Mode));
(Classes.pasの5484行目)

とSysUtils.pas上のFileOpen (ja)を呼び出しています。FileOpenは
const
  AccessMode: array[0..2] of LongWord = (
    GENERIC_READ,
    GENERIC_WRITE,
    GENERIC_READ or GENERIC_WRITE);
  ShareMode: array[0..4] of LongWord = (
    0,
    0,
    FILE_SHARE_READ,
    FILE_SHARE_WRITE,
   FILE_SHARE_READ or FILE_SHARE_WRITE);
  ...
  Result := Integer(CreateFile(PChar(FileName), AccessMode[Mode and 3],
    ShareMode[(Mode and $F0) shr 4], nil, OPEN_EXISTING,
    FILE_ATTRIBUTE_NORMAL, 0));
(SysUtils.pasの5196行目付近)

という実装で、dwDesiredAccessはfmOpenRead→GENERIC_READ、fmOpenWrite→GENERIC_WRITE、fmOpenReadWrite→GENERIC_READ or GENERIC_WRITEとマップされ、dwShareModeはfmShareCompat/fmShareExclusive→0(他の処理からは削除、読み込み、書き込みアクセスできない)、fmShareDenyWrite→FILE_SHARE_READ(他の処理からは読み込みアクセスのみ許可)、fmShareDenyRead→FILE_SHARE_WRITE(他の処理からは書き込みアクセスのみ許可)、fmShareDenyNone→FILE_SHARE_READ or FILE_SHARE_WRITE(他の処理からは読み込み、書き込みアクセスとも許可)とマップされ、dwCreationDispositionはOPEN_EXISTING(ファイルを開きます。指定したファイルが存在していない場合、この関数は失敗します。)が固定的に指定される、ということになります。

これ以外の組み合わせ、たとえば書き込みのために新規にファイルを作成(存在していたら上書き)し、そのファイルに読み込みアクセスのみ許可する、というような場合(dwDesiredAccess = GENERIC_READ or GENERIC_WRITE、dwShareMode = FILE_SHARE_READ、dwCreationDisposition = CREATE_ALWAYS)はTFileStreamを使用するのではなく、直接Windows APIのCreateFileをこれらのパラメータで呼び出し、取得したファイルハンドルでTHandleStreamを作成する、という処理が必要になります。例えばこんな感じでしょうか。
procedure HandleStreamSample(const AFilename: String);
var
  FileHandle: Integer;
  Stream: THandleStream;
begin

  FileHandle := CreateFile(PChar(AFilename),GENERIC_READ or GENERIC_WRITE,
                           FILE_SHARE_READ,nil,CREATE_ALWAYS,
                           FILE_ATTRIBUTE_NORMAL,0);
  if FileHandle < 0 then
  begin
    raise EFCreateError.CreateResFmt(@SFCreateErrorEx,[ExpandFileName(AFileName),
                                     SysErrorMessage(GetLastError)]);
  end;

  Stream := THandleStream.Create(FileHandle);
  try
    { Streamに対する処理 }

  finally
    Stream.Free;
  end;

end;
あるいはCreateFileの他のパラメータ、例えば第6パラメータにFILE_FLAG_...を指定したいような場合などもこのようなコーディングが必要になります。

2011年2月18日

RAD Studio/Delphi/C++Builder XE付属のFinalBuilder/AQtimeのアップデート

RAD Studio/Delphi/C++Builder XEにバンドルされているFinalBuilderとAQtimeがアップデートされ、FinalBuilder Embarcadero Edition(Ent/Arc SKUのみ)が7.0.0.992に、AQtime 7 Standard for Embarcadero RAD Studio XE(Pro/Ent/Arc SKUのみ)が7.10になっています。

AQtime and FinalBuilder Updates for Delphi XE, C++Builder XE and RAD Studio XE
28231 FinalBuilder for Delphi, C++Builder and RAD Studio XE
28230 AQtime 7.1 Standard for Delphi, C++Builder and RAD Studio XE

FinalBuilder 7 Version History

Bug Fixes in AQtime 7.10
New Features in AQtime 7.10

2011年2月16日

Project "Cooper"

2011年02月08日からLas Vegasで行われたDeveloper Solutions Conference (DSConf)でRemObjectsがJava版のDelphi Prism(Oxygene)ともいえるProject "Cooper"を発表しています。

DSConf in Review « RemObjects Blogs

現在RAD Studioに含まれているDelphi Prism("Oxygene")は.NET上で動作するObject Pascal環境ですが、Project "Cooper"はJava(JVM)/Android(Dalvik)上で動作するObject Pascal環境、ということのようです。開発環境はVisual StudioかMonoDevelopに統合されます。詳しくはプレビュービデオで。

YouTube - Project "Cooper" Preview

ただしOxygeneのいくつかの機能、例えば(.NETに強く依存する)LINQのようなものは含まれません。リリースは今年(2011年)で、それ以上のことは今は言えない(That's all we can really say,for now)、とのことです。

ちなみにYouTubeのビデオの最初に出てきますが、"Cooper"は懐かしのツイン・ピークスのクーパー特別捜査官(FBI Special agent Dale Cooper)から取られたそうです。

元ねたはフォーラムのThread: Cooper

関係ありませんが、ここ1日くらいフォーラムのサーバ(forums.embarcadero.com)が不安定のような気がします。

2011年2月14日

Delphiの特定バージョン以前/以後の判定を行う

ライブラリや共通コードを記述していると、DelphiのコンパイラやRTL/VCLの特定の機能が実装されているかどうかを判定して処理を分けたい、ということがよくあります。Delphi 2009のUnicode対応を示す標準条件シンボルの"UNICODE"のように
{$IFDEF UNICODE}
// String = UnicodeString (Delphi 2009 or later)
{$ELSE}
// String = AnsiString (Delphi 2007 or earlier)
{$ENDIF}
とできれば簡単なのですが、Windows.pasのTTokenInformationClassの新しい定義無名メソッド (ja)のサポートのように実装を示す標準条件シンボルの定義が存在しないものは単純に$IFDEFで判定できません。そこでDelphi 6で導入されたCONDITIONALEXPRESSIONSとRTLVersion/CompilerVersionを組み合わせて判定してみます。

Windows.pasにおけるTTokenInformationClassの定義はDelphi 2009(Ver20)で拡張されました。これはRTLの問題ですから、
{$IF (NOT DEFINED(CONDITIONALEXPRESSIONS)) OR (RTLVersion < 20.0)}
// Delphi 2-5 or 6-2007
{$ELSE}
// Delphi 2009 or later
{$IFEND}
で判定可能です(判定を逆にしたい場合はドモルガンの法則により
{$IF (DEFINED(CONDITIONALEXPRESSIONS)) AND (RTLVersion >= 20.0)}
とする)。

一方、Delphi 2010(Ver21)で言語仕様に追加されたクラスコンストラクタとクラスデストラクタについてはコンパイラの問題ですから、
{$IF (NOT DEFINED(CONDITIONALEXPRESSIONS)) OR (CompilerVersion < 21.0)}
// Class constructor/destructor is invalid
{$ELSE}
// Class constructor/destructor is valid
{$IFEND}
として判定することで、Delphi 2009およびそれ以前ではクラスコンストラクタ (ja)/クラスデストラクタ (ja)の代わりにinitialization部 (ja)/finalization部 (ja)で処理を処理を行う、といったことが可能になります。

なお$IFDEF$ENDIFで閉じますが、$IF$IFENDで閉じる、という点に注意が必要です。

2011年2月10日

UAC(User Account Control)の状態を取得する

Windows Vistaで導入されたUAC(User Account Control)が有効になっているかどうかはレジストリのHKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\SystemEnableLUA(DWORD値)が0かどうかで判断できます(0はUAC無効、1はUAC有効)。一方でUACが有効のときにそのプロセスが管理者権限に昇格しているかどうかはOpenProcessToken (ja)でカレントプロセスのハンドルからアクセストークンを取得し、GetTokenInformation (ja)でTokenInformationClassにTokenElevationを指定して取得したTOKEN_ELEVATION構造体のTokenIsElevatedが0かどうかで判断できます(0は昇格していない、非0は昇格している)。

まずプロセスが管理者権限に昇格しているかどうかを判定する処理です。Windows.pasのTTokenInformationClassのTokenElevationやTOKEN_ELEVATION構造体の定義はDelphi 2009で追加されたものなので、それ以前のバージョンでは独自に定義する必要があります。
{$IF (NOT DEFINED(CONDITIONALEXPRESSIONS)) OR (RTLVersion < 20.0)}
type
  TTokenInformationClass = (TokenUser = 1,
                            TokenGroups,
                            TokenPrivileges,
                            TokenOwner,
                            TokenPrimaryGroup,
                            TokenDefaultDacl,
                            TokenSource,
                            TokenType,
                            TokenImpersonationLevel,
                            TokenStatistics,
                            TokenRestrictedSids,
                            TokenSessionId,
                            TokenGroupsAndPrivileges,
                            TokenSessionReference,
                            TokenSandBoxInert,
                            TokenAuditPolicy,
                            TokenOrigin,
                            TokenElevationType,
                            TokenLinkedToken,
                            TokenElevation,
                            TokenHasRestrictions,
                            TokenAccessInformation,
                            TokenVirtualizationAllowed,
                            TokenVirtualizationEnabled,
                            TokenIntegrityLevel,
                            TokenUIAccess,
                            TokenMandatoryPolicy,
                            TokenLogonSid,
                            MaxTokenInfoClass);
  {$EXTERNALSYM TTokenInformationClass}

  PTokenElevation = ^TTokenElevation;
  _TOKEN_ELEVATION = record
    TokenIsElevated: DWORD;
  end;
  {$EXTERNALSYM _TOKEN_ELEVATION}
  TTokenElevation = _TOKEN_ELEVATION;
  TOKEN_ELEVATION = _TOKEN_ELEVATION;
  {$EXTERNALSYM TOKEN_ELEVATION}

function GetTokenInformation(TokenHandle: THandle;
                             TokenInformationClass: TTokenInformationClass;
                             TokenInformation: Pointer;
                             TokenInformationLength: DWORD;
                             var ReturnLength: DWORD): BOOL; stdcall;
  external advapi32 name 'GetTokenInformation';
{$EXTERNALSYM GetTokenInformation}
{$IFEND}

function IsProcessTokenElevated(ProcessHandle: THandle): Boolean;
var
  TokenHandle: THandle;
  TE: TOKEN_ELEVATION;
  dwLength: DWORD;
begin

  Result := False;

  if OpenProcessToken(ProcessHandle,TOKEN_QUERY,TokenHandle) = False then
  begin
    Exit;
  end;

  try
    if GetTokenInformation(TokenHandle,TokenElevation,
                           @TE,SizeOf(TE),dwLength) = False then
    begin
      Exit;
    end;

  finally
    CloseHandle(TokenHandle);
  end;

  Result := (TE.TokenIsElevated <> 0);

end;
これを使用して、レジストリの値をチェックし、UACが有効ならIsProcessTokenElevatedで管理者権限に昇格しているかどうかを確認します。
type
  TUACStatus = (usNoUAC,           // UAC is not implemented
                usUACDisabled,     // UAC is disabled
                usUACEnabled,      // UAC is enabled
                usUACRunAsAdmin);  // UAC is enabled and process token is elevated

function GetUACStatus: TUACStatus;
var
  ReadValue: Integer;
begin

  Result := usNoUAC;

  if CheckWin32Version(6,0) = False then
  begin
    // Windows 2000 or XP: UAC is not implemented
    Exit;
  end;

  with TRegistry.Create do
  begin
    try
      RootKey := HKEY_LOCAL_MACHINE;
      if OpenKeyReadOnly('\Software\Microsoft\Windows\CurrentVersion\Policies\System') = False then
      begin
        raise ERegistryException.Create('Error: Cannot open registry key.');
      end;

      try
        ReadValue := ReadInteger('EnableLUA');
        if ReadValue = 0 then
        begin
          Result := usUACDisabled;
        end
        else
        begin
          Result := usUACEnabled;
        end;

      finally
        CloseKey;
      end;

    finally
      Free;
    end;
  end;

  if Result = usUACEnabled then
  begin
    if IsProcessTokenElevated(GetCurrentProcess) = True then
    begin
      Result := usUACRunAsAdmin;
    end;
  end;

end;
GetUACStatusの戻値がusUACEnabledの場合、REGEDITのように実行時に管理者権限を要求するプロセスを起動するときにUACの確認ダイアログが開くことになります(usNoUAC/usUACDisabledならUACは動作せず、usUACRunAsAdminなら既に昇格済なので確認されない)。

UACが有効かどうかとプロセスが昇格しているかは別々に取得するようにしたほうがいいのかもしれませんが、UAC有効でなければプロセスの昇格も起きないので、ここでは1つにまとめました。

元ねたはDisplay UAC Status - Sysinternals Forums - Page 1EternalWindowsセキュリティ / セキュリティコンテキスト / UAC

2011年2月9日

2011年2月8日

モーダルなフォームのOnShowイベントでそのフォームを閉じる

プログラム的に必要な設定が行われていないなど、何らかの理由でShowModalされた(モーダルな)フォームのOnShowイベントで当該フォームを閉じたい、ということがたまにあります。ところがOnShowイベントで
procedure TForm2.FormShow(Sender: TObject);
begin

  Close;

end;
としてもそのフォームを閉じることはできません。これはTCustomForm.Closeの実装が
procedure TCustomForm.Close;
var
  CloseAction: TCloseAction;
begin
  if fsModal in FFormState then
    ModalResult := mrCancel
  else
    ...
(Delphi 2007のForms.pasの5589行目付近より)
とモーダルなフォームではModalResultをmrCancelに設定するだけで、一方TCustomForm.ShowModalは
function TCustomForm.ShowModal: Integer;
  ...
  try
    Show;
    try
      SendMessage(Handle, CM_ACTIVATE, 0, 0);
      ModalResult := 0;
      repeat
        Application.HandleMessage;
        if Application.Terminated then ModalResult := mrCancel else
        if ModalResult <> 0 then CloseModal;
      until ModalResult <> 0;
      Result := ModalResult;
      SendMessage(Handle, CM_DEACTIVATE, 0, 0);
      if GetActiveWindow <> Handle then ActiveWindow := 0;
    finally
      Hide;
    end;
  ...
end;
(Delphi 2007のForms.pasの5816行目付近より)
となっており、Showの内部でCloseを呼び出してModalResultをmrCancel(など0以外の値)に変更しても、Showから戻ってきてから0に戻されてしまい、"ModalResult <> 0"という終了条件を満たさないためです。

これを回避するには例えばTTimerを使う方法も考えられますが、お手軽な解決として
procedure TForm2.FormShow(Sender: TObject);
begin

  PostMessage(Handle,WM_CLOSE,0,0);

end;
と自分(モーダルなフォーム)にWM_CLOSEメッセージをpost(sendではない)するという方法があります。PostされたWM_CLOSEメッセージはメッセージキューの最後に追加され、repeat-untilループの内部のApplication.HandleMessageでディスパッチされてTCustomForm.WMCloseから最終的にCloseが呼び出されることでModalResultが0以外の値になり、終了条件を満たしてフォームが閉じる、という仕組みです。

2011年2月7日

KSDevをエンバカデロが買収

先日のqadramに続き、エンバカデロ・テクノロジーズがVGSceneDXSceneの開発元であるKSDevのIPを買収し、KSDevのEugene Kryukovさんが"次世代フレームワーク"チームに加わった、とのことです。

Welcome - KSDev - Adobe AIR or WPF like components, 3D in Delphi, Delphi skin, Flash control, Visio like diagram drawing
I am excited to announce that I have joined Embaracadero’s next gen frameworks team leading a very exciting project.
I am working on a very exciting next generation App Development project that will go beyond what the KSDev products were providing. It is safe to say that similar functionality of these frameworks will be made available in future Embarcadero development products. I believe it will be well worth the wait.

というわけで現在のTFormを中心としたフレームワークを置き換える、おそらくはプラットフォーム非依存の新しいフレームワークが計画されている、ということのようです。

元ねたはEmbarcadero purchase KSDev « Delphi Haven

[書籍]プログラミング .NET Framework 第3版

同じくMARUZEN&ジュンク堂書店 渋谷店

プログラミング .NET Framework 第3版 (amazon)/Jeffrey Richter著/藤原雄介訳/日経BP/ISBN 978-4-82229-416-8/7,350円

を購入。

[書籍]C#ルールブック

MARUZEN&ジュンク堂書店 渋谷店

C#ルールブック ~読みやすく効率的なコードの原則 (amazon)/向山隆行、片山優司、阿部順一、寺田和朗、畑中良平著/電通国際情報サービス監修/技術評論社/ISBN 978-4-7741-4502-0/2,604円

を購入。

2011年2月6日

JCL 2.3.0.374/JVCL 3.41 Binary Installer for XEリリース

Delphi /C++Builder XE Starter SKUにコマンドラインコンパイラDCC32が付属していないため、JCL/JVCLのようにインストーラがDCC32を使用してコンパイルを行うタイプのライブラリをStarter SKUにインストールできない、という問題がありましたが、この問題を回避するJCL/JVCLのコンパイル済バイナリのインストーラがCodeCentralにアップロードされています。

28222 Jedi Code Library 2.3.0.374 Binary Installer for XE
28223 Jedi Visual Component Library 3.41 Binary Installer for XE

JVCLのBinary InstallerでJVCLをインストールする場合は、事前にJCLもBinary Installerでインストールしておく必要があるとのことです。

元ねたはJCL and JVCL Binary Installer for XE and Starter Edition | Andy’s Blog and Tools

2011年2月5日

DDevExtensions 2.3リリース

Andreas HausladenさんDDevExtensionsがアップデートされてVersion 2.3になっています。Delphi 2007用の"Set Version Info"の問題を含め、いくつかの不具合が修正され、Delphi 2009/2010/XE用のものが1つのパッケージに統合されています。

DDevExtensions 2.3 available | Andy’s Blog and Tools

2011年2月4日

Firebird 2.1.4 Release Candidate 1リリース

Firebird 2.1.4 Release Candidate 1がリリースされました。いくつかの機能追加と多数の不具合修正が行われています。

Firebird File Repositories (download)
Firebird 2.1.4 Release Candidate 1 Release Notes

2011年2月3日

第19回エンバカデロ・デベロッパーキャンプ開催決定

第19回エンバカデロ・デベロッパーキャンプは以前からの予告どおり2011年03月30日に開催されます。

エンバカデロ・デベロッパーキャンプ
第19回 エンバカデロ・デベロッパーキャンプ

今回はエンバカデロ・テクノロジーズ チーフサイエンティストのAllen Bauerさんが来日、Pulsarのx64サポートやRAD Studio XEについてのディープなセッションが用意されています。また今回もG6セッションでライトニングトーク「共有!みんなの開発事例、開発経験、テクニック」があります。

CFPは頂きましたが、ネタは熟慮中です…。

2011年2月2日

Open Tools APIを使用してIDEのアドオンを作る

A7MさんによるOpen Tools API(OTA)を使用したadd-onの作り方。興味深い。

Open Tools API その0:概要 - C++Builder好きの秘密基地
Open Tools API その1:"Hello,World!"を表示してみる - C++Builder好きの秘密基地
Open Tools API その2:メニューの差し替えとノーティファイアインターフェース - C++Builder好きの秘密基地
Open Tools API その3:ソースエディタへのアクセス - C++Builder好きの秘密基地
Open Tools API その4:続・ソースエディタへのアクセス ソースエディタの「中身」をいじる - C++Builder好きの秘密基地

関連してGnosticeのGirish PatilさんによるCodeRage 5のOTA関係のセッションのリプレイビデオ(約35分)。

Video: Open Tools API を使用して Delphi IDE をより効果的にする方法を探る (英語)

Girish Patilさんによるセッションのデモコードは

Gnostice @ CodeRage Virtual Conference

からダウンロードできます。またOTAについてはGExperts

Erik's Open Tools API FAQ

も参考になるとのことです。

さらにUwe SchusterさんによるRAD Studio XEにおけるOTAの拡張、修正点に関する解説。

RAD Studio XE: Open Tools API changes highlighted Part#1 | Uwe's Delphi blog

2011/02/05追記: その3のリンクを追加。あとは次回のデベロッパーキャンプのA3セッションで。

2011/02/12追記: その4のリンクを追加。

2011年2月1日

エンバカデロ・デベロッパーキャンプツアー・イン名古屋/大阪 2011

以前から予告されていたミニキャンプことデベロッパーキャンプツアーの開催が正式に発表されています。

エンバカデロ・デベロッパーキャンプツアー・イン名古屋 2011
2011年03月02日(水曜日) 13:30-17:00 愛知県産業労働センター

エンバカデロ・デベロッパーキャンプツアー・イン大阪 2011
2011年03月03日(木曜日) 13:30-17:00 大阪ビジネスパーク

いずれも海外担当副社長兼ジェネラルマネージャーのNigel BrownさんがジェネラルセッションとQ&Aセッションを行うようです。

Delphi/C++Builder XE Starterの機能制限

Delphi/C++Builder Starter SKUで動作する機能、動作しない機能に関する情報です(主にIDE関係)。

○ コード補完 ([Ctrl]+[Space])
○ ブロック補完 ("begin"[Enter]で"end;")
× クラス補完 ([Ctrl]+[Shift]+[C])
× ライブテンプレート ("for"[TAB]で"I := 0 to List.Count - 1 do" や "fo"[Ctrl]+[J]で"for"/"forb"/"forin"/"forr"を選択)
× デバッグ中のツールチップヘルプによる値の表示
× デバッグ中のローカル変数ウィンドウ
× コード参照/定義の検索 ([Ctrl]+Click)
○ InterBase Express (IBX)
○ Borland Database Engine (BDE)
× Database Express (DBX), DataSnap, TClinetDataSet
× VCL/RTLソースコード
○ サードパーティコンポーネントのインストール
○ Open Tools API (OTA)

元ねたはフォーラムのEmbarcadero Discussion Forums: Starter Edition is there

2011/02/03追記: Starter SKUにはコマンドラインコンパイラDCC32が含まれないため、DevExpressやJCL/JVCLのようにインストール時にコマンドラインコンパイラを使用するものはインストールに失敗する、という問題が公式フォーラムやjedi newsgroupに報告されています。

Embarcadero Discussion Forums: DevExpress Controls Won't Install in Delphi Startee Edition

とりあえずStrater用にコンパイル済バイナリを同梱するか、ファイル展開後にIDEで.dpkを開いてインストールするか、というのが解決方法でしょうか。

Delphi/C++Builder XE Starter日本語情報

日本語のリリースが公開されています。

エンバカデロ、C++Builder StarterとDelphi Starterを本日より販売開始

Delphi XE Starter Edition
機能一覧 (PDF)

C++Builder XE Starter Edition
機能一覧 (PDF)

Delphi XE Starter Edition / C++Builder XE Starter Edition - Q&A

Starter SKUはESD(Electronic Software Distribution)版のみで価格は18,900円、アップグレードの場合は14,700円になります(いずれも消費税込み)。

"1,000USDルール"はライセンスの追加条項で
Starter エディションに適用される追加条項
お客様が Starter エディションのライセンスを取得された場合には、以下の条項が適用されます。第 2 条第 1 項の権利付与と矛盾する範囲においては、この条項が優先するものとします。お客様は本製品を使用して、(i)お客様が直接または間接に料金を請求せず、ライセンス料金、サービス料金、開発料金、コンサルティング料金、サブスクリプション料金、サポート料金、ホスト設定料金などの報酬を受け取らないソフトウェア、および、(ii)お客様が請求する料金(ライセンス料金、サービス料金、開発料金、コンサルティング料金、サブスクリプション料金、サポート料金、ホスト設定料金など)が年間の累積で 1000 US ドルを超えないソフトウェアを、開発することができます。企業(営利か非営利かを問いません)がソフトウェアの使用権を付与する場合には、(i)企業全体の収益が 1000 US ドルを超えてはならず、(ii)配置する Starter エディション ライセンスの総数が 5 ライセンスを超えてはなりません。
ということになっています。また教育目的にはStarter SKUは適していないので、アカデミックライセンスを検討してほしいとのことです。

ITpro(要登録)、IT Leaders、ZDNet Japanにも記事が出ています。

DelphiとC++ Builderの廉価版が登場、1万4700円から - ニュース:ITpro
エンバカデロ、C++/DelphiのIDEに1万8000円の廉価版、条件は年間収益1000ドル | IT Leaders
エンバカデロ、商用利用も可能なC++BuilderとDelphiの低価格版 - builder by ZDNet Japan

2011年1月31日

Delphi/C++Builder XE Starterエディション公式ページ

またもフライング気味ですが、Delphi/C++Builder XE Starterエディションの公式ページが出現しています(いまのところ英語のみ)。

Delphi XE Starter Edition
Delphi XE Starter Edition and C++Builder XE Starter Edition FAQs
Feature Matrix (PDF)

C++Builder XE Starter Edition
Feature Matrix (PDF)

Starter SKUで何ができてどの機能が使えなくなったのかはPDFのFeature Matrixで確認できます。

元ねたは公式フォーラムのThread: Starter Edition is thereAndreano LanusseさんDelphi XE and C++Builder XE Starter Editions – Officially announced

日本語の情報は明日になる模様です。

2011/02/01追記: 公式なリリースが出ています。

Embarcadero Introduces Starter Editions of C++Builder and Delphi Rapid Application Development Environments

またプロダクトマネージャのMichael Rozlogさん、プロダクトマーケティングマネージャのTim Del Chiaroさんのblogにも記事が出ています。

Michael Rozlog » Blog Archive » Starter Edition Finally Here!!!
Delphi Insider: Delphi XE Starter and C++Builder XE Starter Now Available

2011年1月28日

Delphi/C++Builder Starter Edition

DelphiとC++BuilderのStarter Editionが発表された、という記事がSDTimesに出ています。とりあえず速報ということで。

Embarcadero Introduces Starter Editions of C++Builder and Delphi Rapid Application Development Environments - SD Times: Software Development News

この記事の注目ポイントとしては、特に機能に関する制限は明示されていないものの、1つのネットワークで5ライセンス以内で、それを超える場合やその開発で1,000USD以上の収入がある場合、あるいはDBX/DataSnapを使う場合は上位のSKUにアップグレードしなければならない、というあたりでしょうか。Starter Editionの価格は199USDで、以前のTurbo Editionや他の競合製品のユーザは149USDでアップグレード可能です。

あとは正式発表待ちです。

元ねたは公式フォーラムのThread: Delphi Starter Edition

1,000USDの件は、Users may sell any applications or components developed with these tools until the annual license or service revenue exceeds $1,000 USD or their micro organization exceeds $1,000 in revenue overall.ですので、個人、学生は年間で、組織の場合は累計で、ということになります。

2011/01/29追記: DEKOさんも指摘しています DEKOさんも指摘していますが、SD Timesの記事は予定稿だったはずで、公開時期が来ていない記事が"http://www.sdtimes.com/link/35223"とかいう"ありふれた方法"で見えちゃうのはまずいですよね。いずれにせよプロダクトマーケティングマネージャのTim Del Chiaroさんによると正式発表は来週前半(2011/02/01)に予定されており、(おそらくESDで)購入も可能になるようです。

2011年1月27日

TortoiseSVNの導入 その1

RAD Studio XEではVersion Insight (ja)という形でバージョン管理システムのクライアント機能がIDEに統合され、Apache Subversion (wikipedia)のクライアントとなることができるようになりました(Version InsightそのものはSubversionに限定されるものではなく、将来的にはGit (wikipedia)やMercurial (wikipedia)などにも対応してゆくとのこと)。またDemoもSourceforgeでホストされるようになりました。しかし2010以前のユーザはこの恩恵を受けられません。そこでSubversionのWindowsにおける最も一般的なクライアントであるTortoiseSVN (日本語ミラーサイト)を導入してみるテストです。

まずはTortoiseSVNのインストールですが、Version 1.5以降ではなぜかインストーラがGDI+を必要とします。このためWindows 2000の場合は

Download details: Platform SDK Redistributable: GDI+

からWindowsXP-KB975337-x86-ENU.exeをダウンロードし、展開(実行)して、<展開先>\asms\10\msft\windows\gdiplusのgdiplus.dllをsystem32にコピーします。

次に公式サイトまたは日本語ミラーサイトから最新版(2011/01/26現在で1.6.12)のアプリケーションと日本語パッケージ(Langugage Packsの"ja")のインストーラをダウンロードします(どちらもx86とx64で別のファイルになっているので注意が必要です)。あとはアプリケーション、日本語パッケージの順にインストールし、[スタート]→[プログラム]→[TortoiseSVN]→[Settings]で設定画面を表示して、General(一般)ページのTortoiseSVNのLanguage(言語)を"日本語"に変更して適用すれば準備は完了です。TortoiseSVNのインストールについては

Subversion/TortoiseSVNのインストール - ピノキヲ IT Wiki

が参考になります。ちなみに日本語のオンラインヘルプは

TortoiseSVN

にあります([スタート]→[プログラム]→[TortoiseSVN]→[Help]と同じものです)。ひととおり目を通しておくべきでしょう。

さて、準備は完了といっても、いきなりSubversionのサーバを立てて、というのはいささかハードルが高いので、Nick HodgesさんThe Best way to Get TSmiley, or…. A Subversion Primerに従ってTSmileyをチェックアウトしてみることにしましょう。

まずTSmileyをチェックアウトするフォルダを用意します(ここでは"D:\SVN\TSMILEY"とします)。エクスプローラからこのフォルダを右クリックし、コンテキストメニューから"SVNチェックアウト"を選択します。チェックアウトダイアログでリポジトリのURLを"https://tsmiley.svn.sourceforge.net/svnroot/tsmiley"、チェックアウトディレクトリは"D:\SVN\TSMILEY"のままとして[OK]をクリックするとチェックアウトが始まります。チェックアウトが終了したらエクスプローラで"D:\SVN\TSMILEY"を見てみましょう。確かにTSmileyのファイルがチェックアウトされています。

とりあえずここまで。

2011年1月26日

DDevExtensions 2.2.1リリース

Andreas HausladenさんDDevExtensionsのVersion 2.2の"Use Unit"に問題があったということでVersion 2.2.1がリリースされています。

Bugfix DDevExtensions 2.2.1 | Andy’s Blog and Tools

2011/02/03追記: Delphi 2007用のDDevExtensions 2.2/2.2.1は"Set Version Info"機能が正常に動作しないという不具合が確認されています。この機能が必要な場合は1.6.1または2.0 snapshotまで戻る必要があります。

2011年1月25日

DDevExtensions 2.2リリース

Andreas HausladenさんDDevExtensionsがアップデートされてVersion 2.2になっています。Delphi 7/2007も最新の2.2でサポートされるようになりました。

DDevExtension 2.2 released | Andy’s Blog and Tools

第19回エンバカデロ・デベロッパーキャンプの日程調整中

次回(第19回)のデベロッパーキャンプはエンバカデロのチーフサイエンティストのAllen Bauerさんアジアツアーに合わせる形で2011年03月30日に開催する方向で調整中とのことです。日本的には年度末ですが、Allen Bauerさんが日本に来るのは(多分)4年ぶりで、これを逃すと次の機会はまた5年後くらいになりそう(藤井さん談)なので、ということです。正式なアナウンスは近日中にあると思われます(フライング気味ではありますが、忙しい時期ですのでまずは事前情報ということで)。またその前の2011年03月02日~03日ぐらいに大阪、名古屋でもミニキャンプを行う予定とのことです。このデベロッパーキャンプ、ミニキャンプの日程を含め、しばらくは最新情報に注目、です。

2011/01/26追記: ミニキャンプは名古屋が2011年03月02日、大阪が2011年03月03日で確定した模様です。

2011/02/01追記: 大阪、名古屋のミニキャンプが正式に発表されています。

2011年1月18日

DelphiでKinect

もうあちこちで既出ですが、IT Security LabのAleksさんによる、DelphiでKinectを扱うデモ。とても興味深い。とりあえずメモ。

Having Fun with Kinect and Delphi (examples of 2D and 3D visualization) « IT Security Lab
More 3D Fun with Kinect and Delphi. You can grab and save still 3D frames! « IT Security Lab

Kinectの制御はSimon StuartさんによるTKinect for Delphiを使用しています(TKinect for Delphiには別途Code LaboratoriesCL NUI SDKが必要とのこと)。

元ねたはAmazing demo of TKinect component for Delphi | Andreano Lanusse Blog

2011年1月17日

Visual Studio 2010の新しい"Help3"システム

Visual Studioでは2002以降で(Delphiでも使用している)Document ExplorerによるMicrosoft Help 2(.hxs)形式のヘルプシステムを採用していましたが、やはり不評だったようで、VS2010では新たに"Help3"と呼ばれるヘルプシステムを開発しました。この"Help3"作成の経緯などをMicrosoftのLibrary EXperience (LEX)チームのJeff Braatenさんが明らかにしています。

The Story of Help in Visual Studio 2010
The Story of Help in Visual Studio 2010 (Part 2)
The Story of Help in Visual Studio 2010 (Part 3)

"Help3"はヘルプシステムのパフォーマンス改善、オフライン/オンラインの切替、MSDNとの共存、ローカライズ、適切な内容のヘルプの表示、といった問題を解決するべく開発が行われました。ただ"Help3"は例によって"早すぎた"ようで、Visual Studio 2010 SP1でHelp Viewerも更新される予定です(既にベータ版が利用可能になっています)。

上記のアーティクルでも考察されていますが、現在Windows上で使用できるヘルプシステムは
の事実上4種類です。今後Delphiのヘルプシステムはどうなっていくのでしょう?

2011/01/18追記: "Help3"についてはこんなページもありました。

XLsoft エクセルソフト : Helpware Group - FAR HTML ヘルプ作成ツール - 日本語ホーム
MS Help Viewer 1.0

旧形式からのマイグレーションツールビュアー、対応オーサリングツールもあるようです。

2011年1月14日

日本語文字列照合順番(JIS X 4061:1996)

初めて知ったのですが、日本語の並び替え(いわゆる『五十音順』『電話帳順』)にはJIS規格が存在しています。JIS X 4061:1996の『日本語文字列照合順番 (Collation of Japanese character string)』です。

JSA Web Store - JIS X 4061:1996 日本語文字列照合順番
日本語文字列照合順番 - Wikipedia

この規格では照合順番として"単純照合"、"読み・表記照合"、"代表読み照合"の3種類が定義されています。ただ実装はどれもそれなりに複雑になりそうです。

規格票はJISC 日本工業標準調査会日本工業標準調査会:データベース検索-JIS検索から閲覧することができます(冊子あるいはPDF形式のものは上記のJSA Web Storeや書店で購入することもできますが、たった33ページで1785円です)。

元ねたは中村正三郎さんの乳の詫び状の2011/01/14分の記事。

2011年1月12日

Microsoft Monthly Update 2011/01

今日はMicrosoftのセキュリティアップデートの日です。
MS11-001
MS11-002

2011年1月11日

RadPHPと開発チームをエンバカデロが買収

いまのところEmbarcadero Technologiesqadram softwareのどちらからも公式な発表は行われていませんが、Marco Cantuさん

Embarcadero Buys Quadram (and Hires Jose Leon)

によるとEmbarcaderoがqadramからRadPHP(Delphi for PHP)とその開発チームを買収したようです。Jose Leonさんのタイトルは"Director of Engineering and Branch Director at Embarcadero Technologies"となっており、そのままRadPHP開発チームのディレクタになったようです。

2011/01/25追記: qadram softwareはRadPHPチームとなり、エンバカデロの一部となったようです(完全買収ということ)。

2011年1月6日

InterBase XE日本語版リリース

英語版のみのリリースとなっていたInterBase XEですが、日本語版がリリースされたようです。

エンバカデロ、軽量・ハイパフォーマンスデータベースの最新版InterBase XE日本語版を発表

バージョンはWindows(x86/x64)が10.0.1.335、Linux、Solaris、Macが10.0.0.305となっています(Update 1ということです)。

次期版WindowsはARMをサポート

信頼できない噂として昨年末から語られていた次期版Windows(Windows 8)におけるARMサポートですが、現在行われている2011 International CESでこの噂が本当であり、次期版のWindowsではIntel、AMD(x86/x64)に加えてARMとこれらのSoCをサポートする、というニュースが飛び込んできました。

Next Version of Windows Will Run on System on a Chip (SoC) Architectures from Intel, AMD and ARM: Q&A: In a technology preview at CES, Microsoft demonstrates Windows running on new SoC x86 and ARM-based systems. Microsoftによる公式発表。

2011 International CES:次期版WindowsはARMアーキテクチャをサポート - ITmedia News
MS、次期WindowsでのSoCサポートを明らかに--CES - CNET Japan
マイクロソフト、次期WindowsのARMサポートを正式発表
Microsoft、WindowsをSoCに拡大 - ARMシステムもサポート | パソコン | マイコミジャーナル
[CES2011]Microsoft、次期版WindowsでARMアーキテクチャーをサポートへ - ニュース:ITpro
【PC Watch】 Microsoft、次期WindowsでARMアーキテクチャをサポート
【PC Watch】 【CES 2010レポート】Microsoft基調講演レポート ~次期WindowsのSoCサポートを明言

NVIDIA、Qualcomm、Texas Instrumentsが開発しているARMをベースとしたSoC上でWindowsを動作させることができるようになる模様です(NVIDIAがすんなりとIntelのチップセットから撤退したのはこれがあったからかもしれませんね)。CESでは実際にARM上でWindowsとOfficeが動作しているデモが行われたようです。

Live from Microsoft's CES 2011 keynote -- Engadgetの7:36PMから7:43PMにかけてがARM/SoCサポート関係の発表の実況です。

2011/01/14追記: もう少し詳細な情報が出てきているようです。

【笠原一輝のユビキタス情報局】 Microsoft ダレン・ヒューストン副社長に聞く、ARM版Windowsの正体
CES2011: ARM対応版次期Windowsはどうなる? MS幹部インタビュー

どうやらバイナリ互換性はなく、ネイティブアプリケーションはx86とx64のようにARM用のバイナリを用意する必要がありそうです(.NET Frameworkはおそらくそのまま動くのでしょうけれども)。ロードマップのCommodoreでARMサポートが計画されていることと関連があるのでしょうか…?

2010年12月27日

[書籍]土木建築エンジニアのプログラミング入門

オンラインの日経BP書店

土木建築エンジニアのプログラミング入門/フォーラムエイト著/日経BP/ISBN 978-4-8222-6621-9/2,940円

を購入。この間のデベロッパーキャンプでフォーラムエイトの宮本さんが『近日中にAmazonでも扱いが始まるはずです』といっていましたが、待つのも面倒なので…。全ページ多色刷り、CD-ROM付きで豪華です。

2010年12月22日

Windowsのテストに便利なツールとその使用法

Windows 7/Server 2008 R2上でテストを行うためのツール類とその使用方法を紹介するドキュメントをMicrosoftが公開しています。

Windows のテストに便利なツールとその使用法

紹介されているツールとその使用方法(要約):
  • システムイメージの作成と復元: Windows Automated Installation Kit (WAIK)
  • デバイスのプラグアンドプレイ(PnP)関連のテスト: Plug and Play Driver test (Pnpdtest.exe) (WDKに付属)
  • システムのスリープ・レジュームの移行を自動的に繰り返し実行: Power Management Test Tool (Pwrtest.exe) (WDKに付属)
  • アプリケーションの動作を検証: Application Verifier
  • ネットワークパケットを監視・分析: Network Monitor
  • Windowsポータブルデバイス(WPD)の動作をモニタ: WPD Monitor (WPDMon.exe) (WDK)
  • 問題の再現手順を簡単に記録: 問題ステップ記録ツール (Problem Steps Recorder) (Windows標準)
  • マネージアプリケーションの例外とコールスタックを取得: WinDBG (Windows SDK)
  • カーネルモードドライバ内のエラーを検出: Driver Verifier (Windows標準)
  • ブルースクリーンの問題を調査: Debugging Tools for Windows (Windows SDK)

紹介されているツールのダウンロードリンク:

2010年12月21日

[書籍]デザインのためのデザイン

ジュンク堂書店の吉祥寺店

デザインのためのデザイン (amazon)/Frederick P. Brooks, Jr.著/松田晃一、小沼千絵訳/ピアソン桐原/ISBN 978-4864010047/3,780円

を購入。

2010年12月17日

InterBaseのバックアップ、ジャーナル機能

かなり前になりますが、InterBase 2007以降の新機能の物理バックアップ、ジャーナル関係の興味深いアーティクルがいくつか。

InterBaseのバックアップ機能について
InterBaseのジャーナル機能について
InterBase 2007稼働中にシステム時間を変更した場合の影響について

てきとうな要約:
  • InterBase 2007以降では
    • 従来のフルバックアップ("gbak -b"でODS非依存のバックアップファイルが作成される)
    • 物理バックアップ("gbak -d"で現状の.IBのコピーが作成され、"gbak -d"毎に変更のあったページのみがインクリメンタルに更新される)
    の2種類のバックアップが可能。物理バックアップしたファイルは読み込み専用の状態になっており、"gfix –mode read_write"で書き込み可能(つまりオリジナルと同等)になる。
  • 一方InterBase 2007以降のジャーナルはデータベースに対して"CREATE JOURNAL"とすることでジャーナルファイルが作成されるようになる。更に"CREATE JOURNAL ARCHIVE"とすることでジャーナルアーカイブ機能が有効になり、この状態で"gbak –archive_journals"でジャーナルアーカイブファイルが、"gbak –archive_database"でアーカイブデータベースダンプファイルが、それぞれ作成される。このジャーナルアーカイブファイルとアーカイブデータベースダンプファイルを使用して"gbak –archive_recover"とすることでデータベースを復旧することができる。ジャーナル関係のファイルはバックアップ関係のファイルとは異なりプラットフォーム依存。
  • 運用中にシステム時刻が変更された場合、物理バックアップのインクリメンタルな更新やジャーナルに影響を及ぼすので要注意。

InterBase Serverサービスを停止しなくても"gbak -d"で安全にコピーが取れるようになったということですね。

2010年12月16日

BDE Alternatives Guide

先日のデベロッパーキャンプでも再三BDEはやめましょう、という話が出ていましたが、こんなページがありました。

Data Access for Delphi

BAG="The BDE Alternatives Guide"ですね。

元ねたはNick HodgesさんFlotsam and Jetsam #17

2010年12月15日

Microsoft Monthly Update 2010/12

今日はMicrosoftのセキュリティアップデートの日です。
MS10-090
MS10-091
MS10-092
MS10-093
MS10-094
MS10-095
MS10-096
MS10-097
MS10-098
MS10-099
MS10-100
MS10-101
MS10-102
MS10-103
MS10-104
MS10-105
MS10-106

月間17件、年間106件とも過去最多の数字になります。攻撃手法の進化はあるにせよ、Microsoftの"新しいOSはセキュア"といういつもの主張はお題目に過ぎないことがわかります。頑張っていることはわからないでもないのですけれども…。

2010年12月14日

Delphi/C++Builder初学者のための資料

Delphi-MLや先日のデベロッパーキャンプでも話が出ていましたが、これからDelphi/C++Builderを始めようとすると、入門書の類いはほとんどなく、またヘルプにもチュートリアル的な内容(に限りませんけどね…)がろくに存在しないため、系統的にDelphi/C++Builderを学ぶのが意外に難しい、というのが今の状況です。そこでこのような人のために、入手可能性がそれなりな情報を集めてみました。ただし環境がTurboだったり2007だったり2009だったり、あるいは書籍はもっと古かったりしますが、そこは適当にスルーということで。またデータベース関係についてはDBXのもの以外は軽く読み飛ばしてしまって構いません(いまさらですから)。

EDN(Embarcadero Developer Network): エンバカデロ・テクノロジーズの運営する開発者向情報サイト。過去に入門的な内容のアーティクルがいくつか掲載されました。

EDN/Delphi/ナッキーの「Turbo Delphiはじめて奮戦記」
ナッキーの「Turbo Delphiはじめて奮戦記」(全24回)

EDN/Delphi/ナッキーの「Delphiでビジネスアプリ奮闘記」
第1回 CSVファイルをデータベースへ移行する その1
第2回 CSVファイルをデータベースへ移行する その2
第3回 データベースのレコードを編集する
第4回 データベースのレコードをCSVファイルに保存する

EDN/C++Builder/石原高のオレ流C++独学塾
第1回 オレ流Hello World
第2回 C言語の知識で挑むC++Builder
第3回 CSVファイルを処理してみる
第4回 長い処理をスレッドで実行する

EDN/C++Builder/C++Builder 2009 ファーストガイド
第一回 「C++Builder 2009のインストールと使用許諾」
第二回 「C++Builder2009の起動と終了」
第三回「総合開発環境(IDE)の説明」
第四回「プログラミング手順(前編)」
第五回「プログラミング手順(後編)」
第六回「C++基礎知識(前編)」
第七回「C++基礎知識(後編)」
第八回 「コンポーネント」
第九回「コンポーネントの作成」
第十回「データベースアプリケーションの作成」

書籍: 昨今の出版不況の影響でDelphi/C++Builderの新しい書籍が出ることは考えにくい状況ですが、古本という形でなら入手可能なものもあるようです。このうちオフィシャルコースウェアはどれか一つあれば十分かなと思います(そういう意味ではDelphi 7のものを入手できればいいかと)。また『ナッキーのDelphiはじめて奮戦記』は上記のEDNの記事の書籍化ですが、まとまっている分読みやすいのではないかと思います。

書籍/オフィシャルコースウェア
Borland Delphi4オフィシャルコースウェア 入門編 (amazon)/服部誠著/インプライズ監修/アスキー/1999年/ISBN978-4756130242/
Borland Delphi 4オフィシャルコースウェア (システム開発編) (amazon)/加藤大受著/アスキー/1999年/ISBN978-4756130259/5,040円
Borland Delphi4オフィシャルコースウェア クライアントサーバシステム構築編 (amazon)/真木保著/インプライズ監修/アスキー/1999年/ISBN978-4756131379/5,460円
Borland Delphi 5オフィシャルコースウェア (基礎編) (amazon)/服部誠著/アスキー/1999年/ISBN978-4756132772/2,940円
Borland Delphi 5オフィシャルコースウェア (応用編) (amazon)/井上勉著/アスキー/2000年/ISBN978-4756133236/
Borland Delphi6オフィシャルコースウェア 基礎編 (amazon)/服部誠著/ボーランド監修/アスキー/2002年/ISBN978-4756140029/
Borland Delphi 6オフィシャルコースウェア 応用編 (amazon)/井上勉著/ボーランド監修/アスキー/2002年/ISBN978-4756140036/
Borland Delphi7オフィシャルコースウェア 基礎編 (amazon)/服部誠著/ボーランド監修/アスキー/2003年/ISBN978-4756142283/2,940円
Borland Delphi7オフィシャルコースウェア 応用編 (amazon)/井上勉著/ボーランド監修/アスキー/2003年/ISBN978-4756142290/5,040円

書籍/一般解説書
Delphiの奇跡―普通のプログラマのための真面目な入門書 (amazon)/吉田弘一郎著/技術評論社/1995年/ISBN978-4774102160/
ナッキーのDelphiはじめて奮戦記 (amazon)/佐竹那月著/カットシステム/2007年/ISBN978-4877831332/
Delphi 4プログラミングバイブル (amazon)/Marco Cantu著/篠原慶訳/インプレス/1999年/ISBN978-4844312734/
Delphi 6 プログラミングバイブル (amazon)/Marco Cantu著/篠原慶、光田秀訳/2002年/ISBN978-4844316343/
Turbo DelphiではじめるWindowsプログラミング (amazon)/日経ソフトウエア編/日経BP/2007年/ISBN978-4-8222-2842-2/2,520円

その他
Seventh Delphi Delphi 入門/旧 Delphi 入門/Delphi FAQ

オフィシャルコースウェアあたりは古い内容そのままで構わないんでPDFにでもして配ってくれませんかね…?

2010/12/15追記: RANさんからコメントを頂いたSeventh Delphiさんのリンクを追加しました(Bloggerはコメントが読みにくいので)。

2010年12月10日

浮動小数点数についての解説

Rudy VelthuisさんによるDelphiにおける浮動小数点数(公式には"実数型")の扱いに関する詳細な解説。興味深い。

Rudy's Delphi Corner - Floating point numbers

元ねたは公式フォーラムのEmbarcadero Discussion Forums: Float operations