45
イイイイイイイイイイ Firemonkey イ VCL イイイイ イイイイ

大阪勉強会20151219 Delphi / C++builder インターフェイスの基礎

Embed Size (px)

Citation preview

Page 1: 大阪勉強会20151219 Delphi / C++builder インターフェイスの基礎

インターフェイスの基礎、 Firemonkey と VCL の違いなど毛利春幸

Page 2: 大阪勉強会20151219 Delphi / C++builder インターフェイスの基礎

Firemonkey と VCL の違いなど• って書いてますが。。。• FireMonkey と VCL は全く違うのです。

Page 3: 大阪勉強会20151219 Delphi / C++builder インターフェイスの基礎

復習• 釈迦に説法お許しくださいませ• 次のスライドがわからないければインターフェイスは書けないと思います

Page 4: 大阪勉強会20151219 Delphi / C++builder インターフェイスの基礎

Delphi ポインター (1)

• ポインターvar i: Integer; pi: ^Integer;begin i := 100; pi := @i; Caption := Format('%d', [pi^]);end;

Page 5: 大阪勉強会20151219 Delphi / C++builder インターフェイスの基礎

Delphi ポインター (2)

• ポインターvar rect: TRectF; prect: PRectF;begin rect := TRectF.Create(0,0,100,100); prect := @rect; Caption := Format('x1=%f, y1=%f, x2=%f, y2=%f', [prect^.Left, prect^.Top, prect^.Right, prect^.Bottom]);

end;

Page 6: 大阪勉強会20151219 Delphi / C++builder インターフェイスの基礎

Delphi ポインター (3)

• ポインター渡し

• const ある時と無い時何が違いますか?

procedure TForm1.proc1(const prect: PRectF);begin Caption := Format('x1=%f, y1=%f, x2=%f, y2=%f', [prect^.Left, prect^.Top, prect^.Right, prect^.Bottom]);end;

procedure TForm1.Button1Click(Sender: TObject);var rect: TRectF;begin rect := TRectF.Create(0,0,100,100); proc1(@rect);end;

Page 7: 大阪勉強会20151219 Delphi / C++builder インターフェイスの基礎

Delphi ポインター (4)

• const ポインタアドレス変更不可procedure TForm1.proc1(const prect: PRectF);var rect2: TRectF;begin prect^.Top := 1; rect2 := TRectF.Create(0,0,1,1); prect := @rect2; Memo1.Lines.Append( Format('x1=%f, y1=%f, x2=%f, y2=%f', [prect^.Left, prect^.Top, prect^.Right, prect^.Bottom]));end;

procedure TForm1.Button1Click(Sender: TObject);var rect: TRectF; prect_: PRectF;begin rect := TRectF.Create(0,0,100,100); prect_ := @rect; proc1(prect_); Memo1.Lines.Append( Format('x1=%f, y1=%f, x2=%f, y2=%f', [prect_^.Left, prect_^.Top, prect_^.Right, prect_^.Bottom]));end;

Page 8: 大阪勉強会20151219 Delphi / C++builder インターフェイスの基礎

Delphi ポインター (5)

• var は?procedure TForm1.proc1(var prect: PRectF);var rect2: TRectF;begin prect^.Top := 1; rect2 := TRectF.Create(0,0,1,1); prect := @rect2; Memo1.Lines.Append( Format('x1=%f, y1=%f, x2=%f, y2=%f', [prect^.Left, prect^.Top, prect^.Right, prect^.Bottom]));end;

procedure TForm1.Button1Click(Sender: TObject);var rect: TRectF; prect_: PRectF;begin rect := TRectF.Create(0,0,100,100); prect_ := @rect; proc1(prect_); Memo1.Lines.Append( Format('x1=%f, y1=%f, x2=%f, y2=%f', [prect_^.Left, prect_^.Top, prect_^.Right, prect_^.Bottom]));End;

Page 9: 大阪勉強会20151219 Delphi / C++builder インターフェイスの基礎

Delphi ポインター (class)

• class も同じです ( ポインターのコピーです )TTest = class Fi: Integer; end;

procedure TForm1.proc2(test: TTest);begin test.Fi := 2;end;

procedure TForm1.Button2Click(Sender: TObject);var t: TTest;begin t := TTest.Create; t.Fi := 1; proc2(t); Memo1.Lines.Append(Format(‘%d’, [t.Fi])); 答えは 2 ですend;

Page 10: 大阪勉強会20151219 Delphi / C++builder インターフェイスの基礎

Delphi ポインター (record)

• record は実態のコピーです TTest = record Fi: Integer; end;

procedure TForm1.proc2(test: TTest);begin test.Fi := 2;end;

procedure TForm1.Button2Click(Sender: TObject);var t: TTest;begin t := TTest.Create; t.Fi := 1; proc2(t); Memo1.Lines.Append(Format(‘%d’, [t.Fi])); 答えは 1 ですend;

Page 11: 大阪勉強会20151219 Delphi / C++builder インターフェイスの基礎

Delphi record constructor

• record constructor create は引数ある時だけ TTest = record Fi: Integer; constructor Create(i: Integer); end;

Page 12: 大阪勉強会20151219 Delphi / C++builder インターフェイスの基礎

Delphi record property

• function, procedure, property TTest = record private function geti: Integer; procedure seti(const i: Integer); public Fi: Integer; constructor Create(i: Integer); property i: Integer read geti write seti; end;

var t: TTest;begin t := Ttest.Create(11); t.i := 12;

Page 13: 大阪勉強会20151219 Delphi / C++builder インターフェイスの基礎

Delphi record 継承は無理• record は継承できない TTest = record private function geti: Integer; procedure seti(const i: Integer); public Fi: Integer; constructor Create(i: Integer); property i: Integer read geti write seti; end; TTest1 = record(Ttest) end;[dcc32 エラー ] Unit1.pas(20): E2029 'END' が必要な場所に '(' があります

TTest1 = class(Ttest)   end;[dcc32 エラー ] Unit1.pas(20): E2021 クラス型が必要です

//C++ だと struct a1 {}; struct a2 : public a1{};

Page 14: 大阪勉強会20151219 Delphi / C++builder インターフェイスの基礎

Delphi class

• class   constructor Create; TMyClass = class→ 何も指定してないのに constructor Create; destructor Destroy; override; end;

constructor TMyClass.Create;begin inherited;→ これは TObject に行きますよねend;

Page 15: 大阪勉強会20151219 Delphi / C++builder インターフェイスの基礎

Delphi class

• destructor Destroy; override; TMyClass = class→ 何も指定してないのに constructor Create; destructor Destroy; override; end;

destructor TMyClass.Destroy;Begin inherited;  →同じく TObject に行きますend;

Page 16: 大阪勉強会20151219 Delphi / C++builder インターフェイスの基礎

Delphi method

• procedure function TMyClass = class constructor Create; destructor Destroy; override; public procedure proc_1; function func_1: Boolean; end;

Page 17: 大阪勉強会20151219 Delphi / C++builder インターフェイスの基礎

Delphi クラス継承• クラス継承 TMyClass = class

end; TMyClass1 = class(TMyClass) constructor Create; destructor Destroy; override; end;

Page 18: 大阪勉強会20151219 Delphi / C++builder インターフェイスの基礎

Delphi クラス • virtual, override

• overload

TMyClass = class Fi: Integer; procedure pro1; virtual; end; TMyClass1 = class(TMyClass) constructor Create; destructor Destroy; override; procedure pro1;override; end;

TMyClass1 = class(TMyClass) constructor Create; destructor Destroy; override; procedure pro1;override; procedure pro2(i: Integer);overload; procedure pro2(i: String);overload; end;

Page 19: 大阪勉強会20151219 Delphi / C++builder インターフェイスの基礎

Delphi クラス inherited

• inherited TMyClass = class Fi: Integer; procedure pro1; virtual; end; TMyClass1 = class(TMyClass) procedure pro1;override;end;

procedure TMyClass1.pro1;begin Fi := 2; inherited;end;

Page 20: 大阪勉強会20151219 Delphi / C++builder インターフェイスの基礎

Delphi クラス virtual; abstract;

• virtual; abstract; TMyClass = class Fi: Integer; procedure pro1; virtual; abstract; end; TMyClass1 = class(TMyClass) constructor Create; destructor Destroy; override; procedure pro1;override; procedure pro2(i: Integer);overload; procedure pro2(i: String);overload; end;

procedure TMyClass1.pro1;begin Fi := 2; inherited;  →この場合の inheri は無視されるend;

Page 21: 大阪勉強会20151219 Delphi / C++builder インターフェイスの基礎

Delphi クラス private protected public published

• private protected public published TMyClass1 = class(TMyClass) private → 他所から見えない protected→ 継承は観れる public→ 見れる published→ コンポーネント化した場合オブジェクトインスペクタに出てくる end;

Page 22: 大阪勉強会20151219 Delphi / C++builder インターフェイスの基礎

Delphi class method

• class method TMyClass1 = class(TMyClass) class procedure pro1;end;

class procedure TMyClass1.pro1;begin// Fi := 2; ローカル参照できない inherited;→ インヘリは使えるみたいですend;

TFoo = record class function Foo1: Integer; static;  → static にすれば OK inline; static; でも OK end;

Page 23: 大阪勉強会20151219 Delphi / C++builder インターフェイスの基礎

Delphi method inline

• method inline• ルーチンに inline 指令を指定できるこれは、コンパイラに対して、そのルーチンを実際に呼び出す代わりに、呼び出し側にそのルーチンを含むコードを出力するよう指示します。

Page 24: 大阪勉強会20151219 Delphi / C++builder インターフェイスの基礎

Delphi クラスヘルパー• クラスヘルパー TMyClass1 = class(TMyClass) constructor Create; destructor Destroy; override; class procedure pro1; protected procedure pro2(i: Integer);overload; procedure pro2(i: String);overload; end;

TMyClass1Helper = class helper for TMyClass1 procedure pro3; end;

procedure TMyClass1Helper.pro3;begin pro2(1);end;

var t: TMyClass1;begin t := TMyClass1.Create; t.pro3;end;

Page 25: 大阪勉強会20151219 Delphi / C++builder インターフェイスの基礎

Delphi クラスのネスト• クラスのネスト TMyClass1 = class(TMyClass) constructor Create; destructor Destroy; override; class procedure pro1; private type TBar = class class function func1: Integer; end; procedure pro2(i: Integer);overload; procedure pro2(i: String);overload; end;

Page 26: 大阪勉強会20151219 Delphi / C++builder インターフェイスの基礎

Delphi operator

• operator TOpTest = record Fi: Integer; class operator Add(a, b: TOpTest):TOpTest; end;

class operator TOpTest.Add(a, b: TOpTest): TOpTest;begin a.Fi := a.Fi + b.Fi; Result := a;end;

procedure TForm1.Button2Click(Sender: TObject);vara, b: TOpTest;Begin a := a + b;end;

struct TTest {int Fi = 0;TTest operator+(TTest i1){

i1.Fi = Fi + i1.Fi;return i1;

}};

TTest a;TTest b;a = a + b;

Page 27: 大阪勉強会20151219 Delphi / C++builder インターフェイスの基礎

Delphi operator(2)

• operator

その他いろいろあります

Page 28: 大阪勉強会20151219 Delphi / C++builder インターフェイスの基礎

Delphi TNotifyEvent, TGetStrProc

• よく使いますねtype TMyClass = class FOnEv: TNotifyEvent; property OnEvent: TNotifyEvent read FOnEv write FOnEv; end;

var obj: TMyClass;begin obj:= TMyClass.Create; obj.OnEvent := Self.Button1Click;end;

Page 29: 大阪勉強会20151219 Delphi / C++builder インターフェイスの基礎

BCB TNotifyEvent, TGetStrProc

• よく使いますねstruct TMyClass : public TObject{

TNotifyEvent FOnEv;void __fastcall test() {

if (!(FOnEv == NULL)) {FOnEv(NULL);

}}__property TNotifyEvent OnEv = {read = FOnEv, write = FOnEv};

};__fastcall TForm1::TForm1(TComponent* Owner)

: TForm(Owner){

TMyClass* myObj = new TMyClass();myObj->OnEv = this->DoEv;myObj->test();delete myObj;

}

void __fastcall TForm1::DoEv(System::TObject* Sender){

Caption = L" イベント発生 ";}

Page 30: 大阪勉強会20151219 Delphi / C++builder インターフェイスの基礎

Delphi TProc<T>, TFunc<TResult>

• TProc<T>, TFunc<TResult> procedure TForm1.proc3(plocA: TProc<Integer>);var i: Integer;begin plocA(i);end;

procedure TForm1.proc3(funcA: TFunc<Integer,Single>);var i: Integer; r: SIngle;begin i := 100; r := funcA(i);end;

begin proc3(procedure (i: Integer) begin end); proc3(function (i: Integer): Single begin end);end;

Page 31: 大阪勉強会20151219 Delphi / C++builder インターフェイスの基礎

BCB TProc<T>, TFunc<TResult>

• デルファイと同じですが、• class RTL_DELPHIRETURN DelphiInterface{}なんです。• typedef System::DelphiInterface<TProc>

_di_TProc; があります。

Page 32: 大阪勉強会20151219 Delphi / C++builder インターフェイスの基礎

BCB TProc<T>, TFunc<TResult>

• BCB でラムダ渡す場合struct TMyClass : public TObject{

void __fastcall proc1(const System::Sysutils::_di_TProc proc_){

proc_->Invoke();}

};__fastcall TForm1::TForm1(TComponent* Owner)

: TForm(Owner){

TMyClass* myObj = new TMyClass();myObj->proc1([](){

for (int i =0; i < 10; i++) {Sleep(100);

}});delete myObj;

}

Page 33: 大阪勉強会20151219 Delphi / C++builder インターフェイスの基礎

BCB TProc<T>, TFunc<TResult>

• 旧 BCB で渡す場合 TCppInterfacedObjectclass TSleepFunc : public TCppInterfacedObject<TProc>{public: TSleepFunc(TForm* Form) : FForm(Form) {} virtual void __fastcall Invoke(void) { Sleep(10000); // 時間のかかる処理 //Synchronize メソッドを使う TThread::Synchronize(TThread::CurrentThread, UpdateCaption); } void __fastcall UpdateCaption(void) { FForm->Caption = "OK"; }private: TForm* FForm;};void __fastcall TForm1::Button2Click(TObject *Sender){ Caption = "Start"; TThread::CreateAnonymousThread(new TSleepFunc(this))->Start();}

//////http://www.gesource.jp/weblog/?p=5097

Page 34: 大阪勉強会20151219 Delphi / C++builder インターフェイスの基礎

BCB TProc<T>, TFunc<TResult>

• 旧 BCB で渡す場合 TCppInterfacedObjectstruct aaa : public TCppInterfacedObject<TProc>{

virtual void __fastcall Invoke(void){Sleep(1000);

};};

void __fastcall TForm1::FormCreate(TObject *Sender){

TThread::CreateAnonymousThread(new aaa())->Start();}

Page 35: 大阪勉強会20151219 Delphi / C++builder インターフェイスの基礎

Delphi System.Generics.Collections

• 何かと話題の

Page 36: 大阪勉強会20151219 Delphi / C++builder インターフェイスの基礎

おさらい まとめ• 問題なく 理解できてればインターフェイスも大丈夫です

Page 37: 大阪勉強会20151219 Delphi / C++builder インターフェイスの基礎

インターフェイス• IInterface が元です。• IUnknown, や IInvokable も IInterface ですtype IInterface = interface ['{00000000-0000-0000-C000-000000000046}'] function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall; function _AddRef: Integer; stdcall; function _Release: Integer; stdcall; end; {$IFNDEF SYSTEM_HPP_DEFINES_OBJECTS} {$NODEFINE IInterface} { defined in sysmac.h } {$ENDIF}

IUnknown = IInterface; {$EXTERNALSYM IUnknown} { from unknwn.h or sysmac.h }{$M+} IInvokable = interface(IInterface) end;{$M-} {$NODEFINE IInvokable} { defined in sysmac.h }

Page 38: 大阪勉強会20151219 Delphi / C++builder インターフェイスの基礎

インターフェイス実装• これコンパル通ります。

• 使ってみます

ITest1 = interface(IInterface) ['{046D8512-6809-42F1-859E-3662231092CB}'] procedure proc1(); end; TTest1 = class(TInterfacedObject, ITest1) procedure proc1(); virtual; abstract; end;

var obj: ITest1;begin obj := TTest1.Create; obj.proc1;end;

Page 39: 大阪勉強会20151219 Delphi / C++builder インターフェイスの基礎

インターフェイス実装• これコンパル通ります。

• 使ってみます

ITest1 = interface(IInterface) ['{046D8512-6809-42F1-859E-3662231092CB}'] procedure proc1(); end; ITest2 = interface(IInterface) ['{45E412F1-4275-44D6-9A04-A4065363B70A}'] procedure proc2(); end; TTest1 = class(TInterfacedObject, ITest1, ITest2) procedure proc1(); virtual; abstract; procedure proc2(); virtual; abstract; end;

Page 40: 大阪勉強会20151219 Delphi / C++builder インターフェイスの基礎

インターフェイス実装 2

• Delphi インターフェイスは理解しやすい。var obj: ITest1;begin obj := TTest1.Create; obj.proc1; obj.proc2; エラーend;

var obj: ITest1; obj2: ITest2;begin obj := TTest1.Create; obj.proc1;

obj2 := (obj as TTest1); obj2.proc2;end;

Page 41: 大阪勉強会20151219 Delphi / C++builder インターフェイスの基礎

BCB インターフェイス実装• __interface__interface ITest: public IInterface{public:

virtual void __fastcall proc() = NULL;

};

struct TTest : public TCppInterfacedObject<ITest>{

int FiTest;virtual void __fastcall proc(){

FiTest = 11;};

};using _di_ITest = System::DelphiInterface<Itest>;

__fastcall TForm1::TForm1(TComponent* Owner): TForm(Owner)

{_di_ITest obj = static_cast<ITest* >(new TTest());obj->proc();

}

Page 42: 大阪勉強会20151219 Delphi / C++builder インターフェイスの基礎

TInterfacedObject, TAggregatedObject

• 使い分け• TAggregatedObject は後述する TInterfacedObject の Reference

Counter を共有するクラスです ( 細川さんのブログ )

Page 43: 大阪勉強会20151219 Delphi / C++builder インターフェイスの基礎

BCB TList::Sort()• Sort(TListSortCompare Compare);• typedef int __fastcall (*TListSortCompare)(void * Item1, void * Item2);• なのでただの関数ポインタです。int __fastcall MySort(void *Item1, void *Item2){ return 0;}

std::tr1::shared_ptr<TList> slTemp(new TList());slTemp->Sort(MySort);

Page 44: 大阪勉強会20151219 Delphi / C++builder インターフェイスの基礎

FMX と _di_TProc• FMX で this->Sort() なんてすると• _di_TFmxObjectSortCompare だったりします• TThread::CreateAnonymousThread() とか• System::Sysutils::_di_TProc ThreadProc だったり• インターフェイス渡しです。

Page 45: 大阪勉強会20151219 Delphi / C++builder インターフェイスの基礎