array of constパラメータ。TVarRecの配列に変換される。
C言語のprintfのような、型がバラバラで可変数の引数を渡すことが出来る。Format関数などが使用。大量のoverload関数作るよりはこれかVariantを使ったほうが楽。文字列やExtendedなんかはポインタで受け取るので注意。
DeCALはこれを使ってジェネリックなコンテナを実現している。
単純な使用例
procedure VType(V : array of const); var i: Integer; begin for i :=0 to High(V) do begin case V[i].VType of vtInteger : ShowMessage('整数型: ' + IntToStr(V[i].VInteger)); vtBoolean : ShowMessage('真偽型: ' + BoolToStr(V[i].VBoolean)); vtChar : ShowMessage('文字型: ' + V[i].VChar); vtExtended : ShowMessage('浮動小数点型: ' + FloatToStr(V[i].vExtended^)); vtString : ShowMessage('文字列型: ' + V[i].VString^); vtPointer : ShowMessage('ポインタ型: ' + Format('%p', [V[i].VPointer])); vtPChar : ShowMessage('文字ポインタ型: ' + V[i].VPChar); vtObject : ShowMessage('オブジェクト型: ' + V[i].VObject.ClassName); vtClass : ShowMessage('クラス参照型: ' + V[i].VClass.ClassName); vtWideChar : ShowMessage('UNICODE文字型: ' + V[i].VWideChar); vtPWideChar : ShowMessage('UNICODE文字ポインタ型: ' + WideChar(V[i].VPWideChar)); vtAnsiString : ShowMessage('長い文字列型:' + string(V[i].vAnsiString)); vtCurrency : ShowMessage('通貨型: ' + CurrToStr(V[i].VCurrency^)); vtVariant : ShowMessage('バリアント型: ' + string(V[i].VVariant^)); vtInterface : ShowMessage('インターフェース型'); vtWidestring : ShowMessage('UNICODE文字列型: ' + WideString(V[i].VPWideChar)); vtInt64 : ShowMessage('64Bit整数型: ' + IntToStr(V[i].VInt64^)); end; end; end; procedure TForm1.Button1Click(Sender: TObject); var SStr: Shortstring; AStr: AnsiString; WChar: WideChar; WStr: WideString; C: Currency; I64: Int64; V: Variant; I: IUnknown; begin SStr := 'shortstring'; AStr := 'ansistring'; C := 56.78; V := 'Variant'; I64 := High(Int64); WChar := 'U'; WStr := 'Unicode'; VType([High(Integer),false, 'A', 12.34, SStr, @SStr, PChar(Astr), Form1, TForm1, WChar, @WChar, AStr, C, V, I, WStr, I64 ]); end;
こういうことも出来るよ程度。
THoge = class private FStringArray: array[1..3] of string; public property Str1: string read FStringArray[1] write FStringArray[1]; property Str2: string read FStringArray[2] write FStringArray[1]; property Str3: string read FStringArray[3] write FStringArray[1]; end;
MFCのCWaitCursorっぽいやつ。変数宣言はインターフェースにすること。
type IScopeCursor=interface ['{72F9BF87-DE15-47F7-8AA5-3B5FCE699447}'] procedure Restore; end; TScopeCursor= class(TInterfacedObject,IScopeCursor) private FDefaultCursol: TCursor; FHasRestored: Boolean; public constructor Create(ChangeCursor: TCursor = crHourGlass; DefaultCursor: TCursor = crDefault); destructor Destroy; override; procedure Restore; end; implementation uses Forms; { TScopeCursor } constructor TScopeCursor.Create(ChangeCursor, DefaultCursor: TCursor); begin inherited Create; FHasRestored := False; FDefaultCursol := DefaultCursor; Screen.Cursor := ChangeCursor; end; destructor TScopeCursor.Destroy; begin if (not FHasRestored) and (Screen.Cursor <> FDefaultCursol) then Screen.Cursor := FDefaultCursol; inherited; end; procedure TScopeCursor.Restore; begin if Screen.Cursor <> FDefaultCursol then Screen.Cursor := FDefaultCursol; FHasRestored := True; end; //使用例 procedure TForm1.Button1Click(Sender: TObject); var cur : IScopeCursor; //クラス型では無い begin Cur := TScopeCursor.Create; Sleep(1000); end; procedure TForm1.Button2Click(Sender: TObject); var cur : IScopeCursor; begin Cur := TScopeCursor.Create(crHSplit, crCross); Sleep(1000); end;
C言語でBIT演算でフラグ管理するのと同じことが出来る。
ステータス管理なんかに便利。
色々演算できるが忘れがちなので一通りの操作サンプル。
program Project1; {$APPTYPE CONSOLE} uses SysUtils, TypInfo; type Flag = (BIT1, BIT2, BIT3,BIT4,BIT5, BIT6, BIT7, BIT8); Flags = set of Flag; //要素数8の集合は符号なし8 ビットとして扱われる procedure WriteFlag(F: Flags); var i: Integer; begin Write('[ '); for i := 0 to 7 do begin if (Byte(F) and (1 shl i)) <> 0 then Write(GetEnumName(TypeInfo(Flag), i) + ' '); end; Write(']'); end; procedure WriteBool(B: Boolean); begin WriteLn(BoolToStr(B, True)); end; var F1,F2: Flags; B: byte; begin WriteLn('代入'); F1 := [BIT1]; //F1 = [BIT1] Write(' F1 := [BIT1] = '); WriteFlag(F1); WriteLn; F1 := [BIT1,BIT3]; //F1 = [BIT1,BIT3] Write(' F1 := [BIT1,BIT3] = '); WriteFlag(F1); WriteLn; WriteLn('集合操作ルーチン'); Include(F1,BIT4); //F1 := F1 + BIT4 Write(' Include(F1,BIT4) = '); WriteFlag(F1); WriteLn; Exclude(F1,BIT4); //F1 := F1 - BIT4 Write(' Exclude(F1,BIT4) = '); WriteFlag(F1); WriteLn; WriteLn('和集合'); F1 := [BIT1, BIT2] + [BIT2, BIT3]; //F1 = [BIT1,BIT2,BIT3](AとBの全要素) Write(' [BIT1, BIT2] + [BIT2, BIT3] = '); WriteFlag(F1); WriteLn; WriteLn('差集合'); F1 := [BIT1, BIT2] - [BIT2, BIT3]; //F1 = [BIT1](AにあってBにない要素) Write(' [BIT1, BIT2] - [BIT2, BIT3] = '); WriteFlag(F1); WriteLn; WriteLn('積集合'); F1 := [BIT1, BIT2] * [BIT2, BIT3]; //F1 = [BIT2](AとBともに含まれる要素) Write(' [BIT1, BIT2] * [BIT2, BIT3] = '); WriteFlag(F1); WriteLn; WriteLn('キャスト'); //要素8個までならByte型へキャスト可能。16個ならWord、32個ならLongword Byte(F1) := $FF; Write(' Byte(F1) := $FF = '); WriteFlag(F1); WriteLn; B := 0; F1 := Flags(B); //F1 =[] (直に書くとキャストできない) Write(' F1 := Flags(Byte(0)) = '); WriteFlag(F1); WriteLn; WriteLn('in'); F1 := [BIT1, BIT2]; Write(' BIT1 in '); WriteFlag(F1); Write(' = '); WriteBool(BIT1 in F1); F1 := [BIT1,BIT2,BIT3]; F2 := [BIT1,BIT2,BIT3]; WriteLn('比較'); Write(' '); WriteFlag(F1); Write(' = '); WriteFlag(F2); Write(' = '); WriteBool(F1 = F2); //F1とF2は一致 Write(' '); WriteFlag(F1); Write(' <> '); WriteFlag(F2); Write(' = '); WriteBool(F1 <> F2); F1 := [BIT1, BIT2,BIT3]; F2 := [BIT2, BIT3]; Write(' '); WriteFlag(F1); Write(' >= '); WriteFlag(F2); Write(' = '); WriteBool(F1 >= F2); //F2はF1に含まれていると真 Write(' '); WriteFlag(F1); Write(' <= '); WriteFlag(F2); Write(' = '); WriteBool(F1 <= F2); //F1はF2に含まれていると真 if DebugHook <> 0 then ReadLn; end.
ClientDatasetを右クリックして「項目の作成」を選択して、コレクションエディタで「項目の新規作成」を選択すると、
モジュール 'rtl70.bpl' のアドレス 400056FC でアドレス 4095755C に対する読み込み違反がおきました。.
と出ることがある。
これはdelphiのバグで、登録したパッケージやエキスパートなんかのImage baseが$00400000の時に起こるらしい。
詳細 (borland newsgroup)
ソースがあるパッケージならプロジェクトオプションのイメージベースを他のアドレスに変更して再構築すれば回避できるが、bplしか提供されてない商用のパッケージなどはコンポーネント|パッケージのインストールで該当パッケージのチェックを外してdelphiの再起動が必要になる。
tdumpでbplファイルをダンプ出来るので、 $(DELPHI)\Projects\Bpl やパッケージフォルダのbplを一通り調べてImage baseが$00400000のものは構築しなおしたほうがが無難。
Image baseは$00400000から変更すべきなので、パッケージを作成する時は忘れないように。DLLを作る時も変えておく。exeのときはかまわない。
Helpからは短い名前で引けなくて分かりづらいので対応表。
標準のコンテナはListかHashしかないので
DeCALを使うとSetやMap、C++STLのようなアルゴリズムなんかも使えるようになる。templateではないので癖が多いが付属のpdfが詳しい。
コンテナはMap,MultiMap,Set,MultiSet,HaseSet,MultiHashSet,MultiHashMap,List,Arrayが使え、Iteratorもある。
付いてくるSuperStreamを使うとObjectのシリアライズが便利らしい。
επιστημηさんのSTL samplesを移植してみるとこんなかんじになる。
program Project1; {$APPTYPE CONSOLE} uses SysUtils, DeCAL; procedure ToString(const Obj: DContainer); var Iter: DIterator; begin Write(' ['); Iter := Obj.start; while not atEnd(Iter) do begin Write(IntToStr(GetInteger(Iter))); Advance(Iter); if not atEnd(Iter) then Write(' '); end; WriteLn('] '); end; function Quad(Ptr : Pointer; const Obj : DObject) : DObject; begin Result := Make([asInteger(Obj) * 4]); end; function PlusInt(Ptr : Pointer; const obj1, obj2 : DObject) : DObject; begin Result := Make([asInteger(Obj1) + asInteger(Obj2)]); end; var X: DArray; Y: DArray; Z: DArray; begin X := nil; Y := nil; Z := nil; try X := DArray.create; Y := DArray.create; Z := DArray.create; X.Add([0, 1, 2, 3, 4]); //X.PushBack([0, 1, 2, 3, 4])とも書けるのはstd::vectorよりちょっとうれしい Write('x[] : '); ToString(X); TransformUnary(X, Y, MakeUnary(Quad)); Write('y[n] = x[n] * 4 : '); ToString(Y); TransformBinary(X, Y, Z, MakeBinary(PlusInt)); Write('z[n] = x[n] + y[n] : '); ToString(Z); finally FreeAll([X, Y, Z]); end; if DebugHook <> 0 then ReadLn; end.
*nextPermutation、prevPermutation、mergeSortは未実装。
あまり使っていないが、JCLの方のdebugライブラリのStack系は例外のとき便利。
インストールしたら新規作成->ダイアログに出来るException Dialogは未処理例外が起きると勝手に補足してくれてスタックフレームや動作環境なんかをレポートしてくれるのでとても便利。日本語表示するなら使う前にFontを変更。
配布元
オープンソースのNETWORKライブラリ。
Indyに比べるとシンプルで見通しがいい。
コンポーネントではなくライブラリなのでインストールが楽。
//メール受信サンプル program Project1; {$APPTYPE CONSOLE} uses SysUtils, pop3send; var Pop: TPOP3Send; i: Integer; begin Pop := TPOP3Send.Create; Pop.UserName := 'username'; Pop.Password := 'password'; Pop.TargetHost := '127.0.0.1'; Pop.TargetPort := '110'; Pop.Login; //何も指定しないとAPOPを試して駄目ならLOGINコマンドを使用する WriteLn('LOGIN: '+ Pop.ResultString); Pop.Stat; WriteLn('STAT: ' + Pop.ResultString); for i := 1 to Pop.StatCount do begin Pop.RETR(i); WriteLn('RETR: ' + Pop.FullResult.Text); //タイトルなどはデコードが必要 end; Pop.Logout; Pop.Free; if DebugHook <> 0 then ReadLn; end.
DUnitWizardを入れると雛型を作ってくれる。うちの環境だと時々エラーで落ちることがある。
とりあえずデザインフォーム右クリックで出てくる「Copy Component Name」とエディタのツールバーカスタマイズ(ここにコンパイルとかユニット表示、フォーム表示、フォームユニット切り替えなんかを入れると、とても楽)、TODOListのためにだけでも使う価値がある。IDE Menu Shorcut、Clean Directoriesも便利。
配布元
ドキュメント生成ツール。基本的にJavaDocに近い。
フォームフォントなどの日本語化作業が必要になるがソースは付いてるので難しくない。
モジュールエクスプローラーを使いながら未記入のコメントを埋めていくのは楽。
パラメータや戻り値の書き方に癖がある。というか@param hoge as a THogeなんて書かないとコンフリクト扱い ←コメント自動生成すると勝手に書いてくれた
使い方 LoadFromFileで読み込んでRow[Index]でstringの動的配列を取得できる csv := TCSV.Create; try csv.LoadFromFile('hoge.csv'); for i := 0 to csv.Count -1 do for j := 0 to Length(csv.Rows[i]) -1 do s := s + csv.Rows[i][j]; finally csv.Free; end;