4

インターフェイスに関する Delphi のタイプ セーフは、一意の (オプションですが、入力されている場合は一意の) GUID を設定することで維持されると考えていました。

次に、その質問がありました: OLE経由で Word CentimetersToPoints を呼び出すと、不明なエラーが発生します

そして、在庫の DelphiTWordApplicationコンポーネント (つまり、Word200.pasユニット) を探し始めました。そして、私が見る:

// *********************************************************************//
// Interface: _Application
// Flags:     (4560) Hidden Dual NonExtensible OleAutomation Dispatchable
// GUID:      {00020970-0000-0000-C000-000000000046}
// *********************************************************************//
  _Application = interface(IDispatch)
    ['{00020970-0000-0000-C000-000000000046}']
...
    function CentimetersToPoints(Centimeters: Single): Single; safecall;



// *********************************************************************//
// DispIntf:  _ApplicationDisp
// Flags:     (4560) Hidden Dual NonExtensible OleAutomation Dispatchable
// GUID:      {00020970-0000-0000-C000-000000000046}
// *********************************************************************//
  _ApplicationDisp = dispinterface
    ['{00020970-0000-0000-C000-000000000046}']
...
    function CentimetersToPoints(Centimeters: Single): Single; dispid 371;

または類似:

// *********************************************************************//
// Interface: _Global
// Flags:     (4560) Hidden Dual NonExtensible OleAutomation Dispatchable
// GUID:      {000209B9-0000-0000-C000-000000000046}
// *********************************************************************//
  _Global = interface(IDispatch)
    ['{000209B9-0000-0000-C000-000000000046}']
...
    function CentimetersToPoints(Centimeters: Single): Single; safecall;

// *********************************************************************//
// DispIntf:  _GlobalDisp
// Flags:     (4560) Hidden Dual NonExtensible OleAutomation Dispatchable
// GUID:      {000209B9-0000-0000-C000-000000000046}
// *********************************************************************//
  _GlobalDisp = dispinterface
    ['{000209B9-0000-0000-C000-000000000046}']
...
    function CentimetersToPoints(Centimeters: Single): Single; dispid 371;

そして、私はここで完全に迷っています。

私はそれが好きなのdispinterface「サブクラス」だと思っていましたか?はいの場合、同じプロジェクトで同じ GUID を持つ 2 つのインターフェイスをどのように設定できますか?interfaceTPersistentTObject

それとも、Delphi の新しいclass型から継承された TurboPascalobjectの型など、関連のない別のフレームワークからのものですか? どちら_GlobalDisp_ApplicationDisp使用されていないように見えるWord200.pasので、付録のように、自動インポートされますが、実際には使用されませんか?

_Applicationと の両方を使用してプロジェクトを作成し、_ApplicationDispコンパイルします。しかし、同じGUIDを持っている場合、Delphiはどのようにそれをタイプキャストするのだろうか?

procedure TForm4.Button1Click(Sender: TObject);
 procedure show(const s: Single);
 begin
   ShowMessage(FloatToStr(s));
 end;
begin
  show( WordApplication1.CentimetersToPoints(1.0) );
  show( WordApplication1.Application.CentimetersToPoints(2.0) );
  show( WordApplication1.DefaultInterface.CentimetersToPoints(3.0) );
  show( _ApplicationDisp(WordApplication1.Application).CentimetersToPoints(4.0) );
  show( (WordApplication1.DefaultInterface as _ApplicationDisp).CentimetersToPoints(5.0) );
end;
4

1 に答える 1

3

は、自動化インターフェイスdispinterfaceを使用するための便利な方法です。IDispatch同じ GUID を持っているのはそのためです。裏ではまったく同じものです。

を使用IDispatchしてメソッドを呼び出す場合、通常、呼び出してメソッドGetIdsOfNamesのディスパッチ ID を取得する必要があります。ただし、これらは静的であるため、ディスパッチ ID がわかっている場合は、その手順をスキップして時間を節約できます。そして、それが でdispinterfaceできることです。

でメソッドを呼び出すと、でdispinterface呼び出すことInvokeになりIDispatchますが、 への呼び出しはスキップしますGetIdsOfNames

QueryInterfaceインターフェイスで使用すると、 IDispatch. その後、対応する にキャストできますdispinterface。これは同じインターフェイスですが、 でメソッドを呼び出すと、dispinterfaceその呼び出しが に保存されますGetIdsOfNames

たとえば、Word アプリケーション オブジェクト用のがある場合IDispatch、次のようなコードを記述できます。

var
  WordApp: Variant;
  WordDisp: _ApplicationDisp;
....
WordApp := CreateOleObject('Word.Application');
WordDisp := _ApplicationDisp(IDispatch(WordApp));

キャストは への_ApplicationDisp()呼び出しにすぎませんIntfCopy。これは、 への呼び出しにすぎません_AddRef。そして、次のように書くことができます:

Writeln(WordApp.ProductCode);
Writeln(WordDisp.ProductCode);

どちらも同じ出力を生成します。前者は を呼び出すGetIdsOfNames前に最初に呼び出しInvokeます。後者は に直行しInvokeます。

于 2013-04-30T08:32:51.550 に答える