Oculus SDK 1.3.2 wrapper for Delphi (と、いくつかデモ)
自作プラグイン更新のお知らせ。
10.1 Berlinで動かなかったので直したもの
10.1 Berlinでもそのまま動いたもの
10.1 Berlinのclass helper仕様変更は全然改良じゃないと思った?
皆さんご存じかと思われますが、Delphi 10.1 Berlinがリリースされました。で、新機能の一覧の中にこんなことがさらっと書いてありました。
Delphi コンパイラのその他の改良点 (中略) 可視性のセマンティクスを実行するため、クラス ヘルパやレコード ヘルパでは、拡張元のクラスやレコードの private メンバにはアクセスできません。
なんと、class helperによるprivateメンバーアクセスが制限されてしまいました。class helper内では可視性がprivateとなっていて公開されていないフィールドの読み書きやメソッドのコールなどができるため、VCLやFMXが実装していない機能を自分で追加する時や未修正のバグの対処などで非常に役立つ機能でした。
これが制限されるとなると、こういった処理を記述したソースコードが軒並みコンパイルできなくなるという、バージョン1からの互換性を謳い文句にさえしていたDelphi*1とは思えない愚行です。
とはいえ制限された形でリリースされた以上、何らかの対応を取らなければならないわけで、早速Stack Overflowにも質問が寄せられてるみたいです。しかしそこで回答として寄せられている方法はclass helperを使わずに対処するものなので、それぞれ一長一短があります。
そこで制限を回避して、class helper内からprivateメンバーに再びアクセスする方法を紹介します。
この方法もx86/x64限定という短所はあるにはあるんですが、その代わり以前と同じようにclass helperからprivateメンバーへアクセスすることができます。答えとしては単純なもので、インラインアセンブラを使用するだけです。
unit UnitA; type THoge = class private FPrivateValue: Integer; procedure PrivateMethod; end; end. unit UnitB; type THogeHelper = class helper for THoge public function GetValue: Integer; procedure CallMethod; end; function THogeHelper.GetValue: Integer; asm MOV EAX,Self.FPrivateValue end; procedure THogeHelper.CallMethod; asm CALL THoge.PrivateMethod end;
このようにインラインアセンブラでアクセスすることで10.1 Berlinで導入された制限を回避できます。
たぶんインラインアセンブラで制限することを忘れてるだけなので、アップデートか何かで塞がれそうな気もしますが、少なくともそれまでの繋ぎとしては使えそうです。
(追記)
メソッドコールは引数があると全部アセンブラ上で積まないといけなくて面倒だと思うので、次のような方法を取るとわりと簡単にコールできます。
type THoge = class private procedure PrivateMethod(Arg1, Arg2, Arg3: Integer); end; // 方法1 // メソッドポインタだけ頂く(メソッドポインタをどこかに代入する必要がある等の場合) type THogePrivateProc = procedure(Self: THoge; Arg1, Arg2, Arg3: Integer); THogePrivateMethod = procedure(Arg1, Arg2, Arg3: Integer) of object; function THogeHelper.GetMethodAddr: Pointer; asm LEA EAX,THoge.PrivateMethod end; var hoge: THoge; proc: THogePrivateProc; method: THogePrivateMethod; begin // こっちの方法でもいいし、 proc := hoge.GetMethodAddr; proc(hoge, 1, 2, 3); // こっちの方法でもいい TMethod(method).Code := hoge.GetMethodAddr; TMethod(method).Data := hoge; method(1, 2, 3); end; // 方法2 // ジャンプさせる(単純に呼び出すだけならこっちが簡単) procedure THogeHelper.CallMethod(Arg1, Arg2, Arg3: Integer); asm JMP THoge.PrivateMethod end;
*1:まあ最近は破壊的仕様変更も結構多いけど…
プロジェクトをソートするプラグイン。
どこぞのフォーラムで「無いの?」って言われてたやーつ。
ユニットを新規作成するだけの話。
この投稿はDelphi Advent Calendar 2015の17日目の記事です。
ところで皆さん何か忘れてませんか?
Object Pascal Advent Calendarじゃないですよ!Delphi Advent Calendarですよ!
もっと開発環境の話もぶっ込んでいきましょう!
(あれ…デジャヴ…?)
ユニットの新規作成
Delphiを使っていれば、当然ユニットなんて掃いて捨てるほど作成していることと思いますが、ここで作成されるコードのカスタマイズって意外とできないんですよね。
フォーム等であればリポジトリに登録してカスタムユニットを新規作成することはできるんですが、やはり通常ユニットを作成した段階で自分好みの状態になっていてくれるのが一番ありがたい。
そこでこのプラグイン
Template Replacerはそういったユニットのテンプレートをカスタマイズ可能にするDelphi XE4〜10 Seattle用プラグインです。
使い方は簡単で、パッケージをインストールしてツールメニューに追加される「Template Replacer」を選ぶだけ。すると以下のような画面が出てくるので、usesにあらかじめよく使うユニットを書いておくだとか、スレッドユニットの余計なお世話なコメントを削除しておくといったように、好きにカスタマイズすることができます*1。
上記画像を見れば一目瞭然ですが、テンプレートの指定は空のユニットに限らず設定可能です。スレッドユニットの作成や、コンソールプロジェクトのソースもカスタマイズできます。そして…。
プロジェクトオプションのカスタマイズ
「New Project」を選ぶと、dprではなくdprojのテンプレートをカスタマイズすることができます。
dprojはプロジェクトオプションが記述された設定ファイルです。つまりこれがカスタマイズ可能ということは、デフォルトのプロジェクトオプション*2を設定可能ということです。
これを利用すると、例えば「DCC_DcuOutput(ユニットの出力ディレクトリ)」と「DCC_ExeOutput(EXEの出力ディレクトリ)」を自分がよく使うパスに設定しておいたり、ビルド構成にDEBUGとRELEASE以外のものを最初から追加しておく…なんてことも(たぶん)できるようになります。個人的に出力パスの変更はよくやるので、これがあるだけでもかなり楽になります*3。
入手はこちらから
というわけで
このプラグインを導入すれば、あとはユニットを新規作成するだけの話ですね!(タイトル回収)