2016年5月11日

2016年5月1日

2016/05開催のセミナー

  • Web Seminar
  • Live Seminar

2016年4月28日

RAD Studio/C++Builder 10.1 Berlin April 2016 Hotfix

RAD Studio 10.1 BerlinのHotfixがリリースされています。30530はDataSnapサーバでクライアントから変更の適用または表示の更新を要求すると"Invalid variant type conversion"でエラーになる問題の修正、30531はAndroid 6.0.1のSamsung Galaxy 6 Edgeでデバッグができない問題([RSP-14033] [Debugger | Android]. Can't debug on SAMSUNG GALAXY S7 EDGE with Android 6.0.1)の修正とのことです。

30530 April 2016 RAD Studio 10.1 Berlin Hotfix for DataSnap
30531 April 2016 RAD Studio 10.1 Berlin Hotfix for Samsung Galaxy

2016年4月19日

Firebird 3.0

Firebird 3.0がリリースされています。

Firebird: Firebird 3.0 is released
Firebird: Firebird 3.0.0
Firebird 3.0 Release Notes (PDF)

RAD Studio/Delphi/C++Builder 10.1 Berlinリリース

RAD Studio/Delphi/C++Builder 10.1 Berlinがリリースされています。

エンバカデロ、マルチデバイス向けビジュアル開発ツールの新リリース「RAD Studio 10.1 Berlin」を本日より販売開始

RAD Studio Berlin ヘルプ (en)
リリース ノート (en)
インストール ノート (en)
新機能 (en)

RAD Studio 10.1 Berlin における不具合修正リスト (en)

30510 RAD Studio 10.1 Berlin ISO (incl. Delphi and C++Builder)

30500 FastReport VCL 5 for RAD Studio, Delphi, C++Builder 10.1 Berlin
30501 FastReport FMX for RAD Studio, Delphi and C++Builder 10.1 Berlin
30499 IP*Works for C++Builder 10.1 Berlin
30498 IP*Works for Delphi 10.1 Berlin
30521 RAD Studio 10.1 Berlin FireMonkey Accessibility Pack
30522 BDE Installer for RAD Studio, Delphi, C++Builder 10.1 Berlin

30492 VCL Premium Styles Pack for RAD Studio 10.1 Berlin
30491 FireMonkey Premium Styles Pack for RAD Studio 10.1 Berlin

30553 Jedi Code Library Snapshot Binary Installer for 10.1 Berlin
30554 Jedi Visual Component Library Snapshot Bin-Installer 10.1 Berlin

2016/05/02追記: web(GetIt)インストーラからインストールすると、新規作成でDelphiプロジェクトのActiveXが表示されないという問題が報告されています。

Where is the ActiveX Project Type for Delphi 10.1 Berlin?

レジストリに誤った値が書き込まれるのが原因のようで、 HKEY_CURRENT_USER\SOFTWARE\Embarcadero\BDS\18.0\Known IDE Packages\Delphi の $(BDS)\Bin\delphicompro240.bpl のデータが"__(Untitled)"となっているものを他と同様に"(Untitled)"に変更すればいいようです。

2016/06/15追記: 2016/06/14付でFastReport FMXが更新されたようです。

2016年4月14日

[書籍][オンデマンド版]ハッカーのたのしみ

紀伊國屋書店 新宿南店Hacker's Delight (informIT, amazon(US))の翻訳である

[オンデマンド版]ハッカーのたのしみ (amazon)/Henry S. Warren, Jr.著/滝沢徹、鈴木貢、赤池英夫、葛毅、藤波順久、玉井浩訳/エスアイビー・アクセス/ISBN 978-4-434-20159-2/3,672円

を購入。

なお原著のほうは2012年に2nd Edition (informIT, amazon(US))が出ているようです。また日本語版の出版元であるエスアイビー・アクセスのwebページはIIJ4Uのサービス終了に伴い参照できなくなっています(アーカイブ)。発売元の星雲社はこのご時勢にwebページを持っていない(wikipedia)という昔気質の会社のようですし、オンラインの情報があまりなくてもったいない感じの本ですね…。

2016年4月13日

Microsoft Monthly Update 2016/04

今日はMicrosoftのセキュリティアップデートの日です。
MS16-037
MS16-038
MS16-039
MS16-040
MS16-041
MS16-042
MS16-043
MS16-044
MS16-045
MS16-046
MS16-047
MS16-048
MS16-049
MS16-050

2016年4月1日

[書籍]プリンシプル オブ プログラミング

紀伊國屋書店 新宿本店

プリンシプル オブ プログラミング (amazon)/上田勲/秀和システム/ISBN 978-4-7980-4614-3/2,376円

を購入。

2016/04開催のセミナー

  • Web Seminar
    • 2016/04/13 15:00-15:30(JST) RAD Skill Sprint Webセミナー「RADとOOPを混在させる場合のヒント」
    • 2016/04/27 17:00-20:45(JST) New Highlights of RAD Studio / Delphi / C++Builder
      • 17:00-18:00(JST) 「プレオープンセッション」
      • 18:00-20:00(JST) 「New Highlights of RAD Studio / Delphi / C++Builder」
      • 20:00-20:45(JST) 「RAD Studio新リリースを語る」
      • 20:45-21:00(JST) 「クロージング」
  • Live Seminar

2016年3月9日

Microsoft Monthly Update 2016/03

今日はMicrosoftのセキュリティアップデートの日です。
MS16-023
MS16-024
MS16-025
MS16-026
MS16-027
MS16-028
MS16-029
MS16-030
MS16-031
MS16-032
MS16-033
MS16-034
MS16-035
MS16-036

2016/03/13追記: 2016/03/11にMS16-036が追加されています。

2016年3月4日

RAD Studio/C++Builder 10 Seattle AQTime Hotfix

RAD Studio 10 SeattleのHotfixがリリースされています。RAD Studio/Delphi/C++Builder 10 SeattleでAQTimeを使用している場合の問題を修正するものです。

30489 RAD Studio Deployment hotfix for 10 Seattle (Beta)

Firebird 3.0 Release Candidate 2

Firebird 3.0 Release Candidate 2がリリースされています。

Firebird: Firebird 3.0 Release Candidate 2 is available for testing
Firebird: Firebird 3.0 Release Candidate 2
Firebird 3.0 Release Notes

2016年3月1日

2016/03開催のセミナー

2016年2月26日

Windowsがサーバ版かどうかを調べる

プログラムが動作している環境(Windows)がサーバ版かどうかを調べたいことがまれにあります(WMIでサーバ版Windowsではサポートされていない項目の問い合わせをするときなど)。RTLのソースをちょっと覗いてみたところ、Win32APIのGetVersionEx (ja)関数で取得したOSVERSIONINFOEX構造体のwProductTypeがVER_NT_WORKSTATIONかどうかで判断できるようなのですが、GetVersionEx関数のRemarksにはVerifyVersionInfo (ja)関数を使ったほうがパフォーマンス上望ましい、と書いてあるようなので、VerifyVersionInfo関数(とそのパラメータを組み立てるためにVerSetConditionMask関数の組み合わせ)で実現してみました。
function IsWindowsServer: Boolean;
var
  OSVI: TOSVersionInfoEx;
  ConditionMask: UInt64;
begin

  FillChar(OSVI,SizeOf(TOSVersionInfoEX),0);
  OSVI.dwOSVersionInfoSize := SizeOf(OSVI);
  OSVI.wProductType := VER_NT_WORKSTATION;

  ConditionMask := VerSetConditionMask(0,VER_PRODUCT_TYPE,VER_EQUAL);

  Result := not (VerifyVersionInfo(OSVI,VER_PRODUCT_TYPE,ConditionMask));

end;
OSVERSIONINFOEX構造体を初期化後、wProductTypeにVER_NT_WORKSTATIONを格納し、これに対応する条件マスク(VER_PRODUCT_TYPEがVER_EQUAL)をVerifyVersionInfoで作成してVerifyVersionInfoで問い合わせて、結果がFalse(wProductTypeがVER_NT_WORKSTATION以外)ならサーバ版Windows、という判定です。

Windowsがサーバ版かどうかを調べる(Gist)

2016年2月12日

RAD Studio/Delphi/C++Builder XE7 December 2015 Update

RAD Studio/Delphi/C++Builder XE7のDecember 2015 Updateがリリースされています。有効なアップデートサブスクリプションが必要です。

30477 December 2015 XE7 Update Subscription Update

10 Seattle アップデートサブスクリプション加入ユーザー向け「December 2015 XE7 Update Subscription Update」

RAD Studio/Delphi/C++Builder XE8 December 2015 Update

RAD Studio/Delphi/C++Builder XE8のDecember 2015 Updateがリリースされています。有効なアップデートサブスクリプションが必要です。

30476 December 2015 XE8 Update Subscription Update

10 Seattle アップデートサブスクリプション加入ユーザー向け「December 2015 XE8 Update Subscription Update」

2016年2月10日

2016年2月9日

RAD Studio 2016 ロードマップ

RAD Studioのロードマップは1年くらい前に更新されてそのままになっていました。2015年05月のデベロッパーキャンプのときにMarco Cantuさんに『ロードマップの更新は?』と聞いたところ、『モバイル関係の流れが速いのでロードマップを出すのは難しい』という回答でした(それは困る、とは伝えましたが)。しかし2015年秋のIDERAによる買収によって路線の修正が行われ、2016年01月にロードマップを更新する、というAtanas Popovさんの発言もあり、1月末くらいからどうなってるの?という声も出ていましたが、やっとロードマップが更新されました。

Embarcadero RAD Studio 2016 Product Approach and Roadmap

以下今後のリリースに関する適当な要約:
  • 2016年春リリースのコードネーム"Big Ben"のキーテーマは"品質、最初のユーザ体験と導入"で、新しいインストーラとGetItによりインストールの柔軟性とインストール時間の短縮を図る。2016年のリリースに以下の機能を含めるためチームは作業をしている。
    • VCLとFMXの両方でフォームデザイナをセパレート/フロート可能に
    • C++に関するリファクタリング
    • FireUIアプリケーションプレビュー(IDEのフォームデザイナであらゆるターゲット上でのプレビュー)
    • Firemonkeyの拡張
      • アドレス帳/コンタクトコンポーネント
      • スタイルデザイナとリストビューアイテムデザイナ
      • 多くの機能、リストビューのタッチアニメーション、グリッドの改善、Windowsのアクセラレータキーのサポート、フォント拡張、その他
    • マルチデバイスデザイナの改善
        デバイス上のフォームデザイナプレビュー
      • Android Wearスタイルと新しいFireUIビュー
    • IoT (Internet of Things)
      • Bluetooth LEサポートの拡張
      • そのままでもカスタムでもIoTスマートデバイス、センサ、ウェアラブルを簡単に使えるAPIコンポーネントであるIoT接続フレームワーク
      • Bluetooth LEおよびZ-Waveデバイスをサポートするコンポーネント
      • ThingPoint(EMS機能を拡張するIoTデバイスのためのエンタープライズなアクセスポイント)
    • Windows/VCL
      • Windows 10のBluetooth LEサポートを含むWinRTブリッジの改善
      • DirectX 12サポート
    • Delphiコンパイラおよび言語
      • すべてのプラットフォーム上でUtf8Stringをネイティブサポート
      • Windowsなど非ARCプラットフォーム上でのweak/unsafeインタフェース参照のサポート
    • すべてのプラットフォームでC++ Clang 3.3に移行
    • FireDACドライバ更新(Oracle、DB2、InterBase、SQLite、Advantage)
  • その次の2016年秋リリースのコードネーム"Godzilla"ではDelphi/C++BuilderアプリケーションがLinux上で動くようになる。夏にはDelphi for Linuxのテクニカルプレビューを出すのでぜひフィードバックしていただいて、可能な限り安定して強固なものにしていきたい。秋のリリースを目標としているものは以下の通り。
    • WebBrokerによるApacheモジュールとDataSnap/EMSサポート
    • FireDACによるLinuxデータベースアクセス
    • IoTサポートを含むコンソールアプリケーションのLinuxプラットフォームサポート
    • 公式にはUbuntu ServerとRedHat Enterpriseをサポート(これ以外のディストリビューションの公式サポートは需要に応じて広げてゆく)
    • WindowsベースのIDEとクロスコンパイラ、PAServer経由のデプロイとデバッグ
    • LinuxコンパイラはIntel 64ビットサーバ用で、LLVMベースのARCサポート
  • Linuxサポートの後についてはさらに以下のようなものを考えている。
    • IDEのUIの改善とスタイル
    • すべてのC++コンパイラをより新しいClangベースのものに更新
    • パッケージマネージャおよびインストーラとしての両方でGetItの更なる改善
    • 新しいWindows 10のVCLコンポーネント
    • Firemonkeyのネイティブコントロールの更なる改善
    • Windows 10 Centennialサポート(MicrosoftによるCentennial ユニバーサルWindowsプラットフォームブリッジのリリース待ち)
    • 将来のiOSおよびAndroidのバージョンのサポート

公式の日本語訳も出ました(つか負けた)。

Embarcadero RAD Studio 2016年の製品アプローチとロードマップ

2016年2月5日

整数の中で立っているビットの数を数える

それほど機会が多いわけではありませんが、整数の中で立っているビットの数を数えたいということがあります。C++であればstd::bitsetcountを使えば一発ですが、残念ながらDelphiでは符号なし整数型のヘルパ(TByteHelper/TWordHelper/TCardinalHelper/TUInt64Helper)を含め、標準ではそのような機能がありません。でちょっと検索してみたところ、population countあるいはHamming weightというキーワードが浮かんできました。最近のCPUには専用の命令(x86だとSSE4.2以降のPOPCNT)がありますが、移植性などを考慮して、Delphiで実装してみました。とはいってもCで書かれたものをそのままDelphiに置き換えただけです。詳細や原理については○×つくろーどっとコムさんのその17 ビット演算あれこれ中村実さんのビットを数える・探すアルゴリズムなどを、またx86/x64のPOPCNT命令との比較についてはtakesakoさんのx86x64 SSE4.2 POPCNTあたりを参照してください。
function PopulationCount(Value: UInt8): Integer;
begin

  Value := (Value and $55) + ((Value shr 1) and $55);
  Value := (Value and $33) + ((Value shr 2) and $33);
  Value := (Value and $0F) + ((Value shr 4) and $0F);
  Result := Value;

end;

function PopulationCount(Value: UInt16): Integer;
begin

  Value := (Value and $5555) + ((Value shr 1) and $5555);
  Value := (Value and $3333) + ((Value shr 2) and $3333);
  Value := (Value and $0F0F) + ((Value shr 4) and $0F0F);
  Value := (Value and $00FF) + ((Value shr 8) and $00FF);
  Result := Value;

end;

function PopulationCount(Value: UInt32): Integer;
begin

  Value := (Value and $55555555) + ((Value shr  1) and $55555555);
  Value := (Value and $33333333) + ((Value shr  2) and $33333333);
  Value := (Value and $0F0F0F0F) + ((Value shr  4) and $0F0F0F0F);
  Value := (Value and $00FF00FF) + ((Value shr  8) and $00FF00FF);
  Value := (Value and $0000FFFF) + ((Value shr 16) and $0000FFFF);
  Result := Value;

end;

function PopulationCount(Value: UInt64): Integer;
begin

  Value := (Value and $5555555555555555) + ((Value shr  1) and $5555555555555555);
  Value := (Value and $3333333333333333) + ((Value shr  2) and $3333333333333333);
  Value := (Value and $0F0F0F0F0F0F0F0F) + ((Value shr  4) and $0F0F0F0F0F0F0F0F);
  Value := (Value and $00FF00FF00FF00FF) + ((Value shr  8) and $00FF00FF00FF00FF);
  Value := (Value and $0000FFFF0000FFFF) + ((Value shr 16) and $0000FFFF0000FFFF);
  Value := (Value and $00000000FFFFFFFF) + ((Value shr 32) and $00000000FFFFFFFF);
  Result := Value;

end;
整数の中で立っているビットの数を数える(Gist)

2020/06/01追記: Delphi 10.4 Sydneyでは標準関数(かつ組み込みルーチン(en))としてCountLeadingZeros32(先頭の(MSBからの)連続している0の数/32bit整数)、CountLeadingZeros64(先頭の(MSBからの)連続している0の数/64bit整数)、CountTrailingZeros32(末尾のの(LSBからの)連続している0の数/32bit整数)、CountTrailingZeros64(末尾のの(LSBからの)連続している0の数/64bit整数)、CountPopulation32(1になっているビットの数/32bit整数)、CountPopulation64(1になっているビットの数/64bit整数)が追加されました。これらの関数はコンパイラによってインラインで展開されるため、System.pasなどに定義がありません。またこれらの関数は現時点ではヘルプ上に記述がありません。

2016年2月1日

2016年1月13日

Microsoft Monthly Update 2016/01

今日はMicrosoftのセキュリティアップデートの日です。
MS16-001
MS16-002
MS16-003
MS16-004
MS16-005
MS16-006
MS16-007
MS16-008
MS16-009
MS16-010

2016年1月1日

2016/01開催のセミナー

2015年12月30日

RAD Studio/C++Builder 10 Seattle Update 1 VCL AppAnalytics Hotfix

RAD Studio 10 Seattle Update 1のHotfixがリリースされています。RAD Studio/Delphi/C++Builder 10 SeattleのUpdate 1適用後のVCL AppAnalyticsアプリケーションでサーバとの接続の問題を修正するものです。

30457 10 Seattle Update 1 VCL AppAnalytics Hotfix

2016/02/17追記: 2016/02/16付で更新されています。Pro SKU適用時の問題を解決することのことです。

10 Seattle アップデートサブスクリプション加入ユーザー向け「10 Seattle Update 1 VCL AppAnalytics Hotfix」の更新

2015年12月16日

RAD Studio/C++Builder 10 Seattle Hotfix for iOS 9.2

RAD Studio 10 SeattleのHotfixがリリースされています。RAD Studio/C++Builder 10 SeattleでターゲットがiOS 9.2のときにコンパイルエラーが発生する不具合を修正するものです。

30456 10 Seattle iOS 9.2 C++ Hotfix - December 2015

Team Japan » 10 Seattle 向け「10 Seattle iOS 9.2 C++ Hotfix - December 2015」

明示はされていませんが、RTM、Update 1のどちらにも適用可能と思われます。またアップデートサブスクリプションの加入とは関係なくダウンロードできます。

2015年12月14日

要素数が256を超える集合型を作る

このアーティクルはDelphi Advent Calendar 2015の14日目の記事です(3年ぶり3回目)。

Delphiの特徴的な型として集合型というものがあります。これは基底型となる列挙型部分範囲型の組み合わせを保持できるというもので、C言語のビットフィールドに相当するものですが、各種演算子などが用意されており、非常に便利な言語機能です。しかし集合型にはその基底型の要素数が256以下、正確には順序値として0から255まで、という制約があります。しかし状況によっては256要素を超えるような、あるいは基底型で負値となるものを含むような集合型が欲しいということがあります。そこで既存の集合型になるべく近い形で実装してみることにします。ただしDelphiのジェネリックスはC++のテンプレートとは実装が異なり文法的制約が厳しい(というか値型にはほぼ使えない)ため、ジェネリックスによる汎用の実装ではなく個別の実装になってしまいます。また本来の集合型と同様に使えるよう、参照型(クラスによる実装)ではなく値型である高度なレコード型による実装とします。

まず基底型となる列挙型を定義します。
type
  TFoo = (Foo0 = -1,
          Foo1,
          Foo2,
          Foo3,
          Foo4,
          Foo5,
          FooMax = 256);
順序値が-1から256なのでこれを基底型とする集合型を定義すると
type
  TFooSet = set of TFoo;  // Error: E2028 Sets may have at most 256 elements
(当然ですが)エラーになります。では代替となる高度なレコード型を定義していきます。
const
  BYTE_BIT = 8;  //  Number of bits in byte

type
  TFooSet = record
  private
    FData: array [0..((Ord(High(TFoo)) - Ord(Low(TFoo)) + 1 + (BYTE_BIT - 1)) div BYTE_BIT) - 1] of Byte;
  public
    procedure   Empty;
    function    IsEmpty: Boolean;
  end;

procedure TFooSet.Empty;
begin

  FillChar(FData[0],SizeOf(FData),0);

end;

function TFooSet.IsEmpty: Boolean;
var
  Offset: Integer;
begin

  Result := False;

  for Offset := Low(FData) to High(FData) do
  begin
    if FData[Offset] <> 0 then
    begin
      Result := True;
      Exit;
    end;
  end;

end;
FDataは基底型に対応したビット列を実際に格納する領域で、Emptyはその領域を0クリアするメソッド、IsEmptyはビット列が全て0となっているかどうかをチェックするメソッドです。

次に基底型に対応する要素を追加、削除するメソッド(Include、Exclude)です。単独の要素、複数の要素(array of)のどちらにも対応します。
type
  TFooSet = record
  private
    ...
    class procedure CalcOffsets(Value: TFoo; var AOffset: Integer; var ABit: Byte); static;
  public
    ...
    procedure   Include(Value: TFoo); overload;
    procedure   Include(const Values: array of TFoo); overload;
    procedure   Exclude(Value: TFoo); overload;
    procedure   Exclude(const Values: array of TFoo); overload;
  end;

procedure TFooSet.Include(Value: TFoo);
var
  Offset: Integer;
  Bit: Byte;
begin

  CalcOffsets(Value,Offset,Bit);
  FData[Offset] := FData[Offset] or Bit;

end;

procedure TFooSet.Include(const Values: array of TFoo);
var
  Value: TFoo;
begin

  if Length(Values) > 0 then
  begin
    for Value in Values do
    begin
      Include(Value);
    end;
  end;

end;

procedure TFooSet.Exclude(Value: TFoo);
var
  Offset: Integer;
  Bit: Byte;
begin

  CalcOffsets(Value,Offset,Bit);
  FData[Offset] := FData[Offset] and (not Bit);

end;

procedure TFooSet.Exclude(const Values: array of TFoo);
var
  Value: TFoo;
begin

  for Value in Values do
  begin
    Exclude(Value);
  end;

end;

class procedure TFooSet.CalcOffsets(Value: TFoo; var AOffset: Integer; var ABit: Byte);
var
  RelPos: Integer;
begin

  RelPos  := Ord(Value) - Ord(Low(TFoo));
  AOffset := RelPos div BYTE_BIT;
  ABit    := 1 shl (RelPos mod BYTE_BIT);

end;
CalcOffsetsは基底型の要素がどのビット位置に割り当てられているのかを計算します。

次は基底型の要素が含まれているかどうかを調べるInメソッドです。Inは予約語のため"&"で修飾します。
type
  TFooSet = record
    ...
  public
    ...
    function    &In(Value: TFoo): Boolean;
  end;

function TFooSet.&In(Value: TFoo): Boolean;
var
  Offset: Integer;
  Bit: Byte;
begin

  CalcOffsets(Value,Offset,Bit);
  Result := (FData[Offset] and Bit) <> 0;

end;

あとは何らかの形で文字列化できないと不便なので、16進文字列化するToStringと16進文字列からレコード型に値を入れるParseを用意します。
type
  TFooSet = record
    ...
  public
    ...
    function    ToString(ZeroSuppression: Boolean = True): String;
    class function Parse(const Value: String): TFooSet; static;
  end;

function TFooSet.ToString(ZeroSuppression: Boolean): String;
var
  Index: Integer;
  Len: Integer;
  Offset: Integer;
begin

  Result := '';

  for Offset := Low(FData) to High(FData) do
  begin
    Result := IntToHex(FData[Offset],2) + Result;
  end;

  if ZeroSuppression = True then
  begin
    Index := 1;
    Len := Length(Result);
    while (Index < Len) and (Result[Index] = '0') do
    begin
      Index := Index + 1;
    end;

    if Index > 1 then
    begin
      Delete(Result,1,Index - 1);
    end;
  end;

end;

class function TFooSet.Parse(const Value: String): TFooSet;
var
  Offset: Integer;
  S: String;
begin

  Result.Clear;

  S := StringOfChar('0',(SizeOf(Result.FData) * 2) - Length(Value)) + Value;

  for Offset := Low(Result.FData) to High(Result.FData) do
  begin
    Result.FData[Offset] := StrToInt('$' + Copy(S,(SizeOf(Result.FData) * 2) - (Offset * 2) - 1,2));
  end;

end;

必要な処理はこれで概ね揃いましたが、まだ既存の集合型と同じように使う、というわけにはいきません。そこで演算子オーバロードを用意します。集合型に対応する演算子には"+"(和集合)、"-"(差集合)、"*"(積集合)、"<="(サブセット)。">="(スーパーセット)、"="(等しい)、"<>"(等しくない)、"in"(メンバかどうか)の8つがあります。まず基底型の配列からの暗黙的な型キャストを行うImplicitと、"+"(class operator Add)、"-"(class operator Subtract)、"*"(class operator Multiply)の3つの演算子オーバロードです。
type
  TFooSet = record
    ...
  public
    ...
{$IF CompilerVersion>=24.00}
    class operator Implicit(const Values: array of TFoo): TFooSet;
{$IFEND}
    class operator Add(const lvalue: TFooSet; const rvalue: TFooSet): TFooSet; overload;
{$IF CompilerVersion>=28.00}
    class operator Add(const lvalue: TFooSet; const rvalue: array of TFoo): TFooSet; overload;
{$IFEND}
    class operator Subtract(const lvalue: TFooSet; const rvalue: TFooSet): TFooSet; overload;
{$IF CompilerVersion>=28.00}
    class operator Subtract(const lvalue: TFooSet; const rvalue: array of TFoo): TFooSet; overload;
{$IFEND}
    class operator Multiply(const lvalue: TFooSet; const rvalue: TFooSet): TFooSet; overload;
{$IF CompilerVersion>=28.00}
    class operator Multiply(const lvalue: TFooSet; const rvalue: array of TFoo): TFooSet; overload;
{$IFEND}
  end;

{$IF CompilerVersion>=24.00}
class operator TFooSet.Implicit(const Values: array of TFoo): TFooSet;
begin

  Result.Clear;
  Result.Include(Values);

end;
{$IFEND}

class operator TFooSet.Add(const lvalue: TFooSet; const rvalue: TFooSet): TFooSet;
var
  Offset: Integer;
begin

  Result.Clear;

  for Offset := Low(Result.FData) to High(Result.FData) do
  begin
    Result.FData[Offset] := lvalue.FData[Offset] or rvalue.FData[Offset];
  end;

end;

{$IF CompilerVersion>=28.00}
class operator TFooSet.Add(const lvalue: TFooSet; const rvalue: array of TFoo): TFooSet;
var
  Value: TFoo;
begin

  Result := lvalue;

  for Value in rvalue do
  begin
    Result.Include(Value);
  end;

end;
{$IFEND}

class operator TFooSet.Subtract(const lvalue: TFooSet; const rvalue: TFooSet): TFooSet;
var
  Offset: Integer;
begin

  Result.Clear;

  for Offset := Low(Result.FData) to High(Result.FData) do
  begin
    Result.FData[Offset] := lvalue.FData[Offset] and (not rvalue.FData[Offset]);
  end;

end;

{$IF CompilerVersion>=28.00}
class operator TFooSet.Subtract(const lvalue: TFooSet; const rvalue: array of TFoo): TFooSet;
var
  Value: TFoo;
begin

  Result := lvalue;

  for Value in rvalue do
  begin
    Result.Exclude(Value);
  end;

end;
{$IFEND}

class operator TFooSet.Multiply(const lvalue: TFooSet; const rvalue: TFooSet): TFooSet;
var
  Offset: Integer;
begin

  Result.Clear;

  for Offset := Low(Result.FData) to High(Result.FData) do
  begin
    Result.FData[Offset] := lvalue.FData[Offset] and rvalue.FData[Offset];
  end;

end;

{$IF CompilerVersion>=28.00}
class operator TFooSet.Multiply(const lvalue: TFooSet; const rvalue: array of TFoo): TFooSet;
begin

  Result := lvalue * TFooSet(rvalue);

end;
{$IFEND}
ここで明示的な型キャストを行うExplicitを用意しなかったのは、"TFooSet([Foo0,Foo2])"の"[Foo0,Foo2]"の部分がarray of TFooではなくset of TFooと解釈されてしまいコンパイルエラー(E1012)となる問題を解決できなかったためです。また同様の理由からImplicitはXE3以降、Add/Subtract/Multiplyの2番目のoverload(右項がarray of TFoo)はXE7以降のみ有効です。

次に"<="(class operator LessThanOrEqual)。">="(class operator GreaterThanOrEqual)、"="(class operator Equal)、"<>"(class operator NotEqual)、"in"(class operator In)です。
type
  TFooSet = record
    ...
  public
    ...
    class operator LessThanOrEqual(const lvalue: TFooSet; const rvalue: TFooSet): Boolean; overload;
    class operator GreaterThanOrEqual(const lvalue: TFooSet; const rvalue: TFooSet): Boolean; overload;
    class operator Equal(const lvalue: TFooSet; const rvalue: TFooSet): Boolean; overload;
    class operator NotEqual(const lvalue: TFooSet; const rvalue: TFooSet): Boolean; overload;
    class operator In(lvalue: TFoo; const rvalue: TFooSet): Boolean;
  end;

class operator TFooSet.LessThanOrEqual(const lvalue: TFooSet; const rvalue: TFooSet): Boolean;
var
  Offset: Integer;
begin

  for Offset := Low(lvalue.FData) to High(lvalue.FData) do
  begin
    if (lvalue.FData[Offset] and rvalue.FData[Offset]) <> lvalue.FData[Offset] then
    begin
      Result := False;
      Exit;
    end;
  end;

  Result := True;

end;

class operator TFooSet.GreaterThanOrEqual(const lvalue: TFooSet; const rvalue: TFooSet): Boolean;
var
  Offset: Integer;
begin

  for Offset := Low(lvalue.FData) to High(lvalue.FData) do
  begin
    if (lvalue.FData[Offset] and rvalue.FData[Offset]) <> rvalue.FData[Offset] then
    begin
      Result := False;
      Exit;
    end;
  end;

  Result := True;

end;

class operator TFooSet.Equal(const lvalue: TFooSet; const rvalue: TFooSet): Boolean;
var
  Offset: Integer;
begin

  for Offset := Low(lvalue.FData) to High(lvalue.FData) do
  begin
    if (lvalue.FData[Offset] xor rvalue.FData[Offset]) <> 0 then
    begin
      Result := False;
      Exit;
    end;
  end;

  Result := True;

end;

class operator TFooSet.NotEqual(const lvalue: TFooSet; const rvalue: TFooSet): Boolean;
begin

  Result := not (lvalue = rvalue);

end;

class operator TFooSet.In(lvalue: TFoo; const rvalue: TFooSet): Boolean;
begin

  Result := rvalue.&In(lvalue);

end;
ここでclass operator LessThanOrEqual/GreaterThanOrEqual/Equal/NotEqualにAdd/Subtract/Multiplyのようにarray of TFooを第2パラメータ(右項)とするものを用意しなかったのもExplicitと同様の理由です。

これでTFooSetに対する演算子も一通り揃いました。残るはfor-inループ構造への対応です。必要なものはfor 文を使用するコンテナの繰り返しにあるように、Booleanを返し次の値を指し示すMoveNextメソッドとコレクションに含まれる値を返すCurrentプロパティとを持つようなクラス、インタフェース、レコードのいずれかを返すGetEnumeratorメソッド、ということになります。ここではネストした形でクラスを定義します。
type
  PFooSet = ^TFooSet;
  TFooSet = record
  private
    type
      TEnumerator = class(TObject)
      private
        FContainer: PFooSet;
        FIndex: Integer;
        function GetCurrent: TFoo;
      public
        constructor Create(Container: PFooSet);
        function MoveNext: Boolean;
        property Current: TFoo
                   read GetCurrent;
      end;
  public
    ...
    function GetEnumerator: TEnumerator;
  end;

function TFooSet.GetEnumerator: TEnumerator;
begin

  Result := TEnumerator.Create(@Self);

end;

constructor TFooSet.TEnumerator.Create(Container: PFooSet);
begin

  inherited Create;

  FIndex := Ord(Low(TFoo)) - 1;
  FContainer := Container;

end;

function TFooSet.TEnumerator.MoveNext: Boolean;
begin

  while (FIndex < Ord(High(TFoo))) do
  begin
    FIndex := FIndex + 1;
    if TFoo(FIndex) in FContainer^ then
    begin
      Result := True;
      Exit;
    end;
  end;

  Result := False;

end;

function TFooSet.TEnumerator.GetCurrent: TFoo;
begin

  Result := TFoo(FIndex);

end;
これでTFooSetに対して通常の集合型のように"+"、"-"、"*"のような演算や"="、"<>"のような比較、for..inによる要素の取り出しを行うことができるようになりました。 同様にすることで部分範囲型で値が0..255に収まらないようなものを基底型とするような集合型も実装することができます。 →要素数が256を超える列挙型の集合型(Gist)値範囲が0..255に収まらない部分範囲型の集合型(Gist)

2015年12月10日

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

本日10:00から第31回エンバカデロ・デベロッパーキャンプが新宿NSビルのスカイカンファレンスで行われます。セッション資料は

ダウンロード | デベロッパーキャンプ

からダウンロードできます。またUStreamで全セッションのライブ中継も行われます。

  • 【T1】テクニカルセッション「VCL ユーザーのためのFireMonkey入門」
  • 【G2】ジェネラルセッション「Bigger、Stronger、Focused - エンバカデロ+アイデラで推進される開発者へのコミットメント」
  • 【G3】プロダクトショーケース「エンバカデロの開発ツール最前線」
  • 【T4】テクニカルケーススタディ「『カラオケの鉄人』店舗で、クーポン作成 - DTP並みの印刷システム実現の手法」
  • 【T5】Delphi/C++テクニカルセッション「リモートクライアントから帳票出力 - FastReportサーバーアプリ実装法」
  • 【T6】テクニカルケーススタディ「iPod Touchによる工場内のモバイル化 - 鋼材品質証明と基幹システム連携」
  • 【G7】ライトニングトーク「共有!みんなの開発事例、開発経験、テクニック」

2015年12月9日

Microsoft Monthly Update 2015/12

今日はMicrosoftのセキュリティアップデートの日です。
MS15-124
MS15-125
MS15-126
MS15-127
MS15-128
MS15-129
MS15-130
MS15-131
MS15-132
MS15-133
MS15-134
MS15-135

2015年12月4日

RAD Studio 10 Seattle Update 1 Hotfix

RAD Studio 10 Seattle Update 1のHotfixが2件リリースされています。1件目はIDEが使っているModernThemeのメモリ/GDIリソースリーク(RSP-13023)を修正するものです

30453 10 Seattle Update 1 ModernTheme Hotfix - December 2015

2件目はC++/Clangのローカライズ時の不具合(詳細不明)を修正するものです。

30454 10 Seattle Update 1 C++ Clang FR/DE/JA Hotfix


Team Japan » 10 Seattle アップデートサブスクリプション加入ユーザー向け「10 Seattle Update 1 C++ Clang FR/DE/JA Hotfix」
2 Hot-Fixes for 10 Seattle Update 1

2015年11月20日

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

IderaによるEmbarcadero Technologiesの買収があった影響からか開催が延びていた第31回エンバカデロ・デベロッパーキャンプですが、Ideraから送り込まれた新しいジェネラルマネージャのAtanas Popovさんの来日にあわせて2015年12月10日に開催されることになりました。

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

InterBase XE7 Update 5

InterBase XE7 Update 5がリリースされています。バージョンは12.0.5.366となっています。

30433 InterBase XE7 Update 5 (12.0.5.366) for Windows
30434 InterBase XE7 Update 5 (12.0.5.366) for Linux

InterBase XE7 Update 5 Readme - InterBase (en)

Team Japan » InterBase XE7 Update 5 が公開されました

Firebird 2.5.5

Firebird Ver2.5.5がリリースされています。

Firebird: Firebird 2.5.5
Firebird 2.5 Release Notes (PDF)

2015年11月19日

RAD Studio/Delphi/C++Builder 10 Seattle Update 1

RAD Studio/Delphi/C++Builder 10 SeattleのSubcription Update 1がリリースされています。

30445 Delphi and C++Builder 10 Seattle ISO (includes Update 1)

Subscription Update 1 - RAD Studio

RAD Studio 10 Seattle における不具合修正リスト (en)

RAD Studio 10 Seattle Update 1 公開
Team Japan » サブスクリプション加入ユーザー向け「10 Seattle Subscription Update 1」

Update 1の適用は(上書きではなく)アンインストール後の再インストールとなります。またUpdate Subscription加入者限定となります。

2015年11月11日

Microsoft Monthly Update 2015/11

今日はMicrosoftのセキュリティアップデートの日です。
MS15-112
MS15-113
MS15-114
MS15-115
MS15-116
MS15-117
MS15-118
MS15-119
MS15-120
MS15-121
MS15-122
MS15-123

2015年11月10日

Firebird 3.0 Release Candidate 1

Firebird 3.0 Release Candidate 1がリリースされています。

Firebird: Firebird 3.0 Release Candidate 1
Firebird 3.0 Release Notes

2015年11月1日

IDE Fix Pack 5.94

Andreas HausladenさんIDE Fix PackがアップデートされてVersion 5.94となっています。RAD Studio/Delphi/C++Builder 10 Seattle対応といくつかの新しいパッチが追加されています。

IDE Fix Pack 5.94 released – RAD Studio 10 Seattle support | Andy's Blog and Tools

2015/11/02追記: SSE4.2非サポートのCPUの対応に不具合があり差し替えになっています。ご注意ください。

2015/11開催のセミナー

2015年10月23日

RAD Studio/Delphi 10 Seattle Windows/x64 Compiler Hotfix (Beta)

RAD Studio/Delphi 10 SeattleのDelphi/Windows/x64コンパイラのコンパイル結果が決定論的ではない([RSP-12512] DCC64 codegen isn't deterministic (regression))という不具合が報告されており、これを修正するHotfix(Beta)がリリースされています。

30428 Delphi Win64 Compiler hotfix for 10 Seattle Professional (Beta)
30429 Delphi Win64 Compiler hotfix for 10 Seattle Enterprise (Beta)

10 Seattle向けDelphi Win64コンパイラホットフィックス

最終的な修正は次のアップデート(Update 1)に含まれる予定とのことです。

2015年10月21日

InterBase XE3 Update 4 Hotfix 4

InterBase XE3 Update 4 Hotfix 4がリリースされています。バージョンは11.0.4.828となっています。

30425 InterBase XE3 Update 4 Hotfix 4 (11.0.4.828) for Windows

InterBase XE3 Update 4 Hotfix 3(11.0.4.828)で修正された不具合について

2015年10月16日

[書籍]C++のエッセンス

MARUZEN&ジュンク堂書店 渋谷店A Tour of C++ (amazon.com)の翻訳である

C++のエッセンス (amazon)/Bjarne Stroustrup著/柴田望洋訳/SBクリエイティブ/ISBN 978-4-7973-8477-2/2,376円

を購入。

2015年10月14日

Microsoft Monthly Update 2015/10

今日はMicrosoftのセキュリティアップデートの日です。
MS15-106
MS15-107
MS15-108
MS15-109
MS15-110
MS15-111

2015年10月8日

IDE Fix Pack 5.93 for Delphi XE7 Summer 2015 Update

Andreas HausladenさんIDE Fix PackがDelphi XE7のSummer 2015 Updateに対応しました。この再リリース版ではDelphi XE7のUpdate 1またはSummer 2015 Updateが必要になります。

IDE Fix Pack 5.93 re-release for Summer 2015 XE7 Hotfix | Andy's Blog and Tools

2015年10月6日

RAD Studio/Delphi/C++Builder XE7 Summer 2015 Update

アップデートサブスクリプション導入時に新たに追加された"継続的なメンテナンス"の第1弾としてとして、RAD Studio XE7のSummer 2015 Updateがリリースされています。インストーラ起動時に表示されるとおり、あらかじめXE7のライセンスマネージャでXE8のシリアル番号を登録する必要があるので注意してください。

30410 Summer 2015 XE7 Update Subscription Update

以下の修正がXE8からバックポートされているとのことです。なおCC上でサイズが0バイトと表示されていますが、実際には670MB(703,218,288bytes)あります。

2015年10月5日

Spring4Dのマルチキャストイベントを使う

Delphi/VCLの大きな特徴のひとつである"PMEモデル(Properties, Methods and Events model)"の"E"、イベントハンドラは基本的に関数ポインタ(実際にはTMethod = データポインタ + 関数ポインタ)で実装されており、結果としてイベントはユニキャスト、つまりある事象の通知を受け取れるのは一つのイベントハンドラのみ、ということになっています。しかし状況によってはマルチキャスト、つまり複数のイベントハンドラに事象の通知を送りたい、ということがあります。デザインパターンでいうとオブザーバパターンとなるような状況です。デザインパターンの定石に従って、たとえばBranko StojakovicさんのGoF Patterns in DelphiObserverNick HodgesさんMore Coding in Delphiにあるように、IObserverとISubjectを実装して…というやりかたも考えましたが、マルチキャストで通知したい事象が何種類もある状況だと、何らかの形でジェネリックス化されている実装でないと厳しそうです。そこで探してみると、Spring4DというDI(dependency injection)フレームワークでマルチキャストイベントが実装されているということだったので、これを試してみることにします。なおSpring4DのライセンスはApache License 2.0です(日本語参考訳)。またSpring4Dそのもの(DIコンテナとしてのSpring4D)については第28回エンバカデロ・デベロッパーキャンプのLTの岡野さんプレゼンテーション資料が非常に参考になります。

まずSpring4Dのなかでマルチキャストを実現しているのはEvent<T>レコード型になります。これを使用するのに必要なユニットですが、Source\Baseフォルダにある
  • Spring.pas
  • Spring.inc
  • Spring.ResourceStrings.pas
  • Spring.Events.Base.pas
  • Spring.Events.pas
  • jedi.inc
です。もちろんSpring4Dをインストールして検索パスにSpring4D関係のフォルダを追加しても構いませんが、マルチキャストだけを試すのであればこれらのファイルをコピーして.pasファイルをプロジェクトに追加するだけでも大丈夫です。

では実際にEvent<T>でマルチキャストを試してみます。今回はメインフォームからモードレスなサブフォームをいくつか表示して、フォーム上のボタンクリックの発生と、その累計回数を各フォームに通知します。

まず通知のためのイベントと、イベントを登録/削除するインタフェースを定義します。
type
  TNotifyNumber = procedure (Sender: TObject; Number: Integer) of object;

  ISubject = interface
    procedure Add(AEvent: TNotifyNumber);
    procedure Remove(AEvent: TNotifyNumber);
  end;
TNotifyNumberが通知のためのイベントハンドラの型、ISubjectがそのイベントハンドラを登録/削除する機能を持たせたインタフェースです。メインフォーム、サブフォームの両方で使用するので別ユニットで定義しておきます。次はメインフォームです。
uses
  Spring, ...

type
  TForm1 = class(TForm,ISubject)
    ...
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    FEvent: Event<TNotifyNumber>
  public
    procedure Add(AEvent: TNotifyNumber);
    procedure Remove(AEvent: TNotifyNumber);
  end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  FEvent := Event<TNotifyNumber>.Create;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  FEvent.Clear;
end;

procedure TForm1.Add(AEvent: TNotifyNumber);
begin
  FEvent.Add(AEvent);
end;

procedure TForm1.Remove(AEvent: TNotifyNumber);
begin
  FEvent.Remove(AEvent);
end;
メインフォームはISubjectインタフェースを継承するようにして、AddとRemoveを実装します。Event<T>はレコード型ですが、内部の適切な初期化のためにclass function Createを呼び出しておく必要があります。AddとRemoveでは単にEvent<T>のAddRemoveを呼び出すだけです。一方サブフォームでは
type
  TForm2 = class(TForm)
    ...
  private
    FSubject: ISubject;
  public
    property Subject: ISubject
               read  FSubject
               write FSubject;
  end;
メインフォームをISubjectとして保持するためのプロパティを用意します。これでメインフォームからサブフォームを生成、表示する処理は
procedure TForm1.Button1Click(Sender: TObject);
begin
  with TForm2.Create(Self) do
  begin
    Subject := Self;
    Show;
  end;
end;
となります。サブフォーム側ではボタンクリックで任意にマルチキャストイベントを登録、削除できるようにしてみます、
type
  TForm2 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Label1: TLabel;
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    ...
    procedure DoNotifyNumber(Sender: TObject; Number: Integer);
  public
    ...
  end;

procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Subject.Remove(DoNotifyNumber);
  Action := caFree;
end;

procedure TForm2.Button1Click(Sender: TObject);
begin
  Subject.Add(DoNotifyNumber);
end;

procedure TForm2.Button2Click(Sender: TObject);
begin
  Subject.Remove(DoNotifyNumber);
end;

procedure TForm2.DoNotifyNumber(Sender: TObject; Number: Integer);
begin
  Label1.Caption := 'Notified number is ' + IntToStr(Number);
end;
procedure DoNotifyNumberがマルチキャストイベントのイベントハンドラで、これをButton1/Button2のクリックイベントでSubjectにAdd/Removeすることで登録、削除します。最後にメインフォーム側からのマルチキャストイベントの呼び出しです。
type
  TForm1 = class(TForm,ISubject)
    ...
    Label1: TLabel;
    Button2: TButton;
    procedure Button2Click(Sender: TObject);
  private
    FCount: Integer;
    ...
  public
    ...
  end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  FCount := FCount + 1;
  Label1.Caption := IntToSTr(FCount);
  FEvent.Invoke(Self,FCount);
end;
Selfと1ずつ増える整数値(FCount)でEvent<T>のInvokeメソッドを呼び出すだけです(正確にはInvokeはイベントハンドラ型(<T> = <TNotifyNumber>)のプロパティで、Invoke(...)とすることでメソッドの呼び出しになる)。

Spring4DのEventがよくできていることもあってそれほど難しくはないと思います(気をつけなければならないのはclass function CreateによるEvent<T>の明示的な初期化くらい)。ただEvent<T>のTには通常のイベントハンドラ(procedure ... of object)だけでなく、無名メソッド(reference to ...)も入れられるのですが、この場合Event<T>で保持されるものが自動的に生成される無名メソッド値(TInterfacedObjectの派生クラスのインスタンス)であり、そのポインタをAddの呼び出し側(TForm2)では知ることができないためRemoveできない、という点には注意が必要です。

2015年10月1日

RAD Studio/Delphi/C++Builder 10 Seattle PAServer Hotfix

RAD Studio/Delphi/C++Builder 10 SeattleのPAServer Hotfixがリリースされています。OS X 10.11対応とiOS 9 SDK対応とのことです。またUpdate Subscriptionとは関係なくダウンロードできます。

30398 PAServer Hotfix for Delphi, C++Builder and RAD Studio 10 Seattle

PAServer Hotfix for RAD Studio 10 Seattle - iOS 9 and OS X El Capitan
How to use custom Info.plist XML to support iOS 9's new App Transport Security feature

2015/10開催のセミナー

2015年9月24日

GetIt経由でインストールしたTurboPack LockBox 3.5がRAD Studio XE8と10 Seattleで干渉する問題とその暫定解決策

RAD Studio XE8で導入されたGetItパッケージマネージャは、簡単にコンポーネントなどのパッケージをIDEに登録することができる便利なツールです。ところがここに登録されているTurboPack LockBox 3.5のパッケージ名がXE8のものと10 Seattleのもので同一("LockBox3DR.bpl"、"LockBox3DD.bpl")となっており、パッケージは環境変数PATHに従って検索されるため、同一環境上のXE8と10 Seattleの両方にLockBoxを入れると先にインストールしたIDEが誤って別のバージョンのbplファイルを読み込んでしまいエラーになる、という現象があります(2015/09/24現在)。この問題、既にTurboPackのメンテナであるRomanさんのほうでは認識しており、GitHub上のリポジトリではXE8のほうのLIBサフィックスには220、10 Seattleのほうには230がつけられているのですが、GetItで配布されるものにはまだこれらの変更が反映されていないようです。

ということで暫定解決策ですが、次の3つが考えられます。
  1. GetItを使わずGitHubから最新のもの(XE810 Seattle)をチェックアウトしてインストールする。
  2. 誤動作するほうのバージョンのIDEのショートカットの作業フォルダにbplの保存先を明示的に指定する(XE8なら"C:\Users\Public\Documents\Embarcadero\Studio\16.0\Bpl"、10 Seattleなら"C:\Users\Public\Documents\Embarcadero\Studio\17.0\Bpl")。
  3. 自分でLIBサフィックスを指定しなおす。具体的には
    1. "ファイル"→"プロジェクトを開く"でXE8なら"C:\Users\<username>\Documents\Embarcadero\Studio\16.0\CatalogRepository\LockBox-3.5.0\packages\Delphi"、10 Seattleなら"C:\Users\<username>\Documents\Embarcadero\Studio\17.0\CatalogRepository\LockBox-3.5.0\packages\Delphi"にあるDelphi.groupprojを開く
    2. プロジェクトマネージャでLockBox3DD.bplを右クリック→アンインストール
    3. 当該バージョンのbplフォルダにある"LockBox3DR.bpl"と"LockBox3DD.bpl"を削除する
    4. LockBox3DD.bpl、LockBox3DR.bplのプロジェクトオプションでターゲットを"すべての構成 - すべてのプラットフォーム"にしておいて、"説明"のLIBサフィックスを220(XE8)または230(10 Seattle)に変更する
    5. "プロジェクト"→"すべてのプロジェクトをコンパイル"でコンパイルする(DEBUGビルドのみでいいようです)
    6. LockBox3DR220.bpl(XE8)またはLockBox3DR230.bpl(10 Seattle)を右クリック→インストール
    という手順になります。この場合、GetItからLockBox 3.5をアンインストールしたときに完全に削除されなかったりするかもしれませんが、その場合はアンインストール後にマニュアルでbplフォルダの下のLockBox*.*とCatalogRepositoryフォルダ(C:\Users\<username>\Documents\Embarcadero\Studio\XX.X\CatalogRepository)の下のLockBox-3.5.0フォルダを削除すればいいようです。
(C++Builderをお使いの方は"packages\CBuilder\CBuilder.groupproj"だったり"LockBox3CR.bpl"だったり"LockBox3CD.bpl"だったりしますが、適当に読み替えてください)

休日にもかかわらず鋭い指摘をいただいた、おに(@onimaro2010)さんに感謝いたします。とりあえずまとめました。

2015年9月21日

[書籍]C++ 11/14 コア言語

同じく紀伊國屋書店新宿本店

C++ 11/14 コア言語 (amazon)/江添亮著/ドワンゴ/ISBN 978-4-04-869424-7/4,104円

を購入。

[書籍]Effective Modern C++

紀伊國屋書店新宿本店Effective Modern C++ (amazon.com)の翻訳である

Effective Modern C++ (amazon)/Scott Meyers著/千住治郎訳/オライリージャパン/ISBN 978-4-87311-736-2/4,104円

を購入。

2015年9月12日

RAD Studio/Delphi/C++Builder 10 Seattle DUnitX Update

RAD Studio/Delphi/C++Builder 10 SeattleのDUnitX Updateがリリースされています。DUnitX関係のファイルの更新のようです。

30368 DUnitX Update for RAD Studio, Delphi, and C++Builder 10 Seattle

2015年9月9日

Microsoft Monthly Update 2015/09

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

2015年9月3日

[書籍]Delphi in Depth: ClientDataSets 2nd Edition

同じくCreateSpaceで注文した

Delphi in Depth: ClientDataSets 2nd Edition (CreateSpace, Amazon US)/Cary Jensen Ph.D.著/CreateSpace/ISBN 978-1505840186/34.99USD

が配送されてきました。34.99USD("More Coding in Delphi"のついでなのでshippingは考えないことにして)=6,191JPY(暫定、1USD=124.41JPY)でした。

[書籍]More Coding in Delphi

CreateSpaceで注文した

More Coding in Delphi (CreateSpace, Amazon US)/Nick Hodges著/CreateSpace/ISBN 978-1941266106/39.99USD

が配送されてきました(今回の配送はi-parcel/佐川急便でした)。2015/08/18に注文して16日目の到着、39.99USDにShippingの9.77USD("Delphi in Depth: ClientDataSets 2nd Edition"の分も込み)で締めて49.76USD=6,721JPY(暫定、1USD=123.74JPY)でした。

2015年9月1日

2015/09開催のセミナー

2015年8月27日

[書籍]暗号技術入門 第3版

ジュンク堂書店 吉祥寺店

暗号技術入門 第3版 (amazon)/結城浩著/SBクリエイティブ/ISBN 978-4-7973-8222-8/3,240円

を購入。

2015年8月19日

[書籍]Object Pascal Handbook

CreateSpaceで注文した

Object Pascal Handbook (CreateSpace, Amazon US)/Marco Cantu著/CreateSpace/ISBN 978-1514349946/46.50USD

が配送されてきました(今回の配送はi-parcel/佐川急便でした)。2015/08/07に注文して13日目の到着、46.50USDにShippingの7.38USDで締めて53.88USD=6,721JPY(暫定、1USD=123.74JPY)6,823JPY(1USD=126.634JPY)でした。ちなみにかなり分厚いです(実測で31mmでした)。日本語版も期待してます。

Microsoft OOB Update 2015/08

Microsoftの定例外のセキュリティアップデートがリリースされています。
MS15-093

2015年8月12日

2015年8月5日

IDE Fix Pack 4.4 for Delphi 2007 Windows 10 Edition

Andreas HausladenさんIDE Fix Pack for Delphi 2007のWindows 10対応版がリリースされています。Windows 7およびそれ以前では4.4を、Windows 8/8.1では4.3を、Windows 10では4.4 Windows 10 Editionを、というようにWindowsのバージョンによって対応が分かれているので注意が必要です。

IDE Fix Pack 4.4 for Delphi 2007 – Windows 10 Edition | Andy's Blog and Tools

2015年8月4日

IDE Fix Pack 5.93

Andreas HausladenさんIDE Fix PackがアップデートされてVersion 5.93となっています。今回はWindows 10対応(Windows 10が関数アライメントのパディングにNOPではなくINT3を使うことに対応)だけとのことです。

IDE Fix Pack 5.93 – Windows 10 support | Andy's Blog and Tools

2015年8月1日

2015/08開催のセミナー

2015年7月15日

2015年7月8日

7th anniversary

この1年間(2014/07/08-2015/07/07)のエントリは71で、週平均1.4弱でした。相変わらずお知らせばっかりでしたね。続いてアクセス解析の統計情報から月別ページビュー(PV)を。

2014/07: 4,460
2014/08: 4,002
2014/09: 4,259
2014/10: 4,087
2014/11: 3,752
2014/12: 3,876
2015/01: 3,500
2015/02: 3,431
2015/03: 4,314
2015/04: 4,882
2015/05: 4,209
2015/06: 4,434

2014/07-2015/06合計: 49,206

ついに50,000PV/yearを切ってしまいましたが、最近だと書籍関係のまとめが好評のようです。

最近のDelphi関係の話題といえばやはりアップデートサブスクリプションの導入でしょう。開発ツールに(売り切りではなく)いわゆるサブスクリプションモデルは適合しにくいと思うんですけれども、そのあたりは(いかにもアメリカンにアバウトな感じで)修正しながら、ということになるようです。現状のアップデートサブスクリプションモデルのもとでは、アップデートサブスクリプションに入るか、入らないのであれば使いたいバージョンの次のバージョンが出たところでアップグレードする(買ったバージョンではなく直前のバージョンを使う)、ということになるでしょうか。歪んでますねぇ。

ここのところ仕事もオーバフロー寸前のところで動いていてなかなか記事も書けないのですが、直近では久しぶりに新規の案件が入ってXE8にアップグレードしましたし、新たにDataSnapを本格的に使うので、このあたりでまたアウトプットを出していければと思っています。あとは名古屋でやるという勉強会的なイベントに行ければいいなぁ。また1年間お付き合いください。

2015年7月1日

2015/07開催のセミナー

2015年6月24日

DataSnapサーバまとめ

DataSnapサーバを作るにあたって、ヘルプのDataSnap アプリケーションの開発あたりに載っていなかったり、載っていても気をつけたほうがいいと個人的に思ったことをまとめました(ユニットやクラス、あるいはそのリンクはDelphi XE8のものです)。
  • サーバメソッドでサポートされているデータ型

  • クラスインスタンスのマーシャリング/アンマーシャリング

    • Delphiのオブジェクト(クラスインスタンス)は、基本的に送信側でTJSONMarshalMarshalメソッドでTJSONValueにマーシャリング(変換)したものを送信し、受信側では受信したTJSONValueをTJSONUnMarshalUnmarshalメソッドでアンマーシャリング(逆変換)して元のクラスのインスタンスに戻します(アンマーシャリングの結果の型はTObjectなのでasで本来のクラスにキャストします)。
    • クラスインスタンスのリスト(TObjectListTObjectList<T>)はそのままではマーシャリング/アンマーシャリングできないため、
      var
        Values: TJSONArray;
        Item: TFoo;
        List: TObjectList<TFoo>;
      begin
        ...
        for Item in List do
        begin
          Values.AddElement(Marshal.Marshal(Item));
        end;
      
      のようにそれぞれの要素をマーシャリングしたものをTJSONArrayAddElementメソッドで追加していって、そのTJSONArrayを受け渡して、
      var
        Values: TJSONArray;
        Item: TJSONValue;
        List: TObjectList<TFoo>;
      begin
        ...
        for Item in Values do
        begin
          List.Add(UnMarshal.Unmarshal(Item) as TFoo);
        end;
      
      TJSONArrayのItems[]プロパティ(またはenumerator)で取り出したJSONValueをアンマーシャリングする、という方法が考えられます。
    • RTL経由で適切にシリアライズできないようなクラスのメンバを扱う場合は、マーシャラ(TJSONMarshal)およびアンマーシャラ(TJSONUnMarshal)に特定の型またはメンバに対応する変換/逆変換処理をRegisterConverterRegisterReverterで登録して処理させる、ということになります。詳細はユーザー オブジェクトのシリアル化を参照。

  • TJSONValueとその派生クラスについて

    • DelphiでJSON形式の値を扱うときにはTJSONValueの派生クラスを使用します。
      • TJSONNullはJSONのnull値に対応します。
      • TJSONFalse/TJSONTrueはJSONの真偽値(false/true)に対応します。
      • TJSONStringはJSONの文字列値に対応します。
      • TJSONNumberはJSONの数値(整数、浮動小数点数)に対応します。
      • TJSONArrayはJSONの配列("JSON形式の値"の配列)に対応します。
      • TJSONObjectはJSONのオブジェクト("文字列のキーと値のペア"の順序付けされていない集合)に対応します。"文字列のキーと値のペア"はTJSONPairとして実装されています。ペアはAddPairメソッドで追加し、逆に文字列のキーからペアを取り出すにはGetメソッドを使用します。

  • サーバクラスのインスタンスのライフサイクルについて

  • セッションの管理について

    • サーバメソッド内でセッションを取得するときはTDSSessionManager.GetThreadSessionメソッドを使用します。またセッションに関する操作にはSessionIdが必要になります。詳細はサーバー側セッション管理を参照。
    • 全てのセッションに対して処理を行いたいときはTDSSessionManagerのForEachSessionメソッドを使用して、
      TDSSessionManager.Instance.ForEachSession(
          procedure (const Session: TDSSession)
          begin
            //
          end);
      
      とします。
    • セッションごとにデータを保持させたいときは、TDSSessionのPutObjectGetObjectHasObjectRemoveObjectの各メソッドで特定のキー(文字列)と結びつける形でTObjectのインスタンスの保持、取得、問い合わせ、削除ができます。保持させたデータはセッションが所有しており、セッションが破棄されるときに解放されます。
    • セッションが生成、破棄されるごとに処理を行いたい場合はTDSSessionManagerのシングルトンインスタンスであるInstanceAddSessionEventでイベント(イベントハンドラや無名メソッド)を登録します(RemoveSessionEventで登録を削除することもできます)。
      TDSSessionManager.Instance.AddSessionEvent(
          procedure(Sender: TObject;
                    const EventType: TDSSessionEventType;
                    const Session: TDSSession)
          begin
            case EventType of
              SessionCreate:
              begin
                // Session is created
              end;
      
              SessionClose:
              begin
                // Session is closed
              end;
            end
          end);
      

  • 重量コールバック(クライアントコールバック)の管理

    • TDSCallbackTunnelManagerのAddTunnelEventRemoveTunnelEventメソッドでトンネルおよびコールバックの登録、解除を通知するコールバック関数を登録、解除できます。
      TDSCallbackTunnelManager.Instance.AddTunnelEvent(
          procedure(Sender: TObject; const EventItem: TDSCallbackTunnelEventItem)
          begin
            case EventItem.EventType of
              TunnelCreate:
              begin
                // Tunnel is created
              end;
      
              TunnelClose:
              begin
                // Tunnel is closed
              end;
      
              TunnelClosedByServer:
              begin
                // Tunnel is closed by user
              end;
      
              CallbackAdded:
              begin
                // Callback is added
              end;
      
              CallbackRemoved:
              begin
                // Callback is removed
              end;
            end;
          end);
      

  • TCP/IP接続を監視

2015/06/25追記: Mat DeLongさんとJim Tierneyさんのブログを参考に一部の項目を追加。

2015年6月19日

RAD Studio/Delphi/C++Builder XE8 Update 1

RAD Studio/Delphi/C++Builder XE8のUpdate 1がリリースされています。

30278 General Update 1 for RAD Studio, Delphi, and C++Builder XE8
30282 Subscription Update 1 for RAD Studio, Delphi, and C++Builder XE8

30284 Delphi and C++Builder XE8 ISO (includes Subscription Update 1)

30304 Boost for RAD Studio & C++Builder XE8 Subscription Update 1

XE8 Update 1 のリリース ノート - RAD Studio (en)

RAD Studio XE8, Delphi XE8, C++Builder XE8 の Subscription Update 1における不具合修正リスト
Subscription Update 1 Fix List for RAD Studio XE8, Delphi XE8, and C++ Builder XE8

XE8からはUpdate Subscriptionに加入しているかどうかで受け取れるバグフィックス、アップデートが異なる、ということになりましたが、XE8 Update 1もGeneral Update 1とSubscription Update 1で内容に差があります。General Update 1には" Community toolbar"、"iOS 8 simulator fix"、"Several files missing from the initial XE8 delivery"のみが含まれ、"Favorites in welcome page"、"Fast search of Bluetooth LE devices"、"Improved robustness of IDE productivity features"、"Improvements in multi-device previews"はSubscription Update 1のみ、となっています。

2015/07/08追記: C++Builder XE8のBoost 1.39用のヘッダファイルの更新(30304)が追加されています。

2015年6月10日

2015年6月1日

2015/06開催のセミナー