0

ActiveX ライブラリからのコールバックで OleVariant にアクセスしようとしています。

TLB でのイベント ハンドラーの定義は次のとおりです。

procedure(ASender: TObject; var structQSnap: {??structVTIQSnap}OleVariant) of object;

TLB での structVTIQSnap の定義は次のとおりです。

structVTIQSnap = packed record
  bstrSymbol: WideString;
  bstrListingExch: WideString;
  bstrLastExch: WideString;
  fLastPrice: Double;
  nLastSize: Integer;
  bstrBbo: WideString;
  bstrBidExch: WideString;
  fBidPrice: Double;
  nBidSize: Integer;
  bstrAskExch: WideString;
  fAskPrice: Double;
  nAskSize: Integer;
  fHighPrice: Double;
  fLowPrice: Double;
  fOpenPrice: Double;
  fClosePrice: Double;
  nCumVolume: Integer;
  bstrTradeCondition: WideString;
  nQuoteCondition: Integer;
  bstrCompanyName: WideString;
  f52WeekHigh: Double;
  f52WeekLow: Double;
  fEps: Double;
  nSharesOutstanding: Integer;
  nSpCode: Integer;
  fBeta: Double;
  bstrExDivDate: WideString;
  nDivFreq: Integer;
  fDivAmt: Double;
  nAvgVolume: Integer;
  bstrCusip: WideString;
  fVwap: Double;
  bstrUpdateTime: WideString;
  bstrExch: WideString;
  nSharesPerContract: Integer;
end;

正常にコンパイルされますが、bstrSymbol にアクセスしようとするたびに、「無効なバリアント操作」が表示されます。

 procedure TForm1.HandleVTIQuoteSnap(ASender: TObject; var structQSnap: OleVariant);
 var
    symbol: WideString;
 begin
    symbol := structQSnap.bstrSymbol; // this line causes the exception
 end;

Delphi で structQSnap とそのプロパティにアクセスするにはどうすればよいですか?

C# では、この関数はイベント ハンドラーに対して正常に機能します。

    void vtiQ_OnVTIQSnap(ref vtiLib.structVTIQSnap structQSnap)
    {
        MessageBox.Show("Got qsnap for " + structQuoteSnap.bstrSymbol);            
    }

何か案は?

4

4 に答える 4

8

Delphi の ActiveX インポート ウィザードは、structVTIQSnap タイプ (レコードのように見える) を適切に処理する方法を認識しておらず、デフォルトの OleVariant を使用しているだけだと思います。生成された ..._TLB.pas ファイルに structVTIQSnap などの型宣言がありますか? OleVariant の代わりにそれを使用してみてください。

procedure (ASender: TObject; var structQSnap: structVTIQSnap) of object;

タイプはおそらく「パックされたレコード」として宣言されます。

于 2009-01-27T17:12:11.957 に答える
1

structQSnapをこの構造体へのポインタに型キャストしてみることができます。何かのようなもの

PstructVTIQSnap = ^structVTIQSnap;
structVTIQSnap = packed record
   bstrSymbol: WideString;
   // other stuff...
end;

procedure TForm1.HandleVTIQuoteSnap(ASender: TObject;
  var structQSnap: OleVariant);
var
  ps: PstructVTIQSnap;
  symbol: WideString;
begi
  ps := PstructVTIQSnap(structQSnap.VPointer^);
  symbol := ps.bstrSymbol;
  ...
end;

ただし、理解できないのは次のとおりです。C#コードのrefから、構造を2回マーシャリングする必要があることを理解しています。1回はライブラリからコールバックに、2回目はライブラリに戻ります。これは、varByRef フラグ ($4000) を VType に設定する必要があることを意味しますが、コメントで指定した値 (3484) は小さすぎますか?

于 2009-01-27T16:33:23.483 に答える
0

TVarData(structQSnap).VType で返されるものを調べてみてください。

それはうまくいくかもしれません:

 var
   symbol: WideString;
   rec: structVTIQSnap;
 begin
    rec := structVTIQSnap(structQSnap);
    symbol := rec.bstrSymbol; 
 end;
于 2009-01-27T15:45:34.300 に答える
0

「structVTIQSnap」を「OleVariant」と見なしている理由がわかりません。私には奇妙な翻訳に思えます。配列などの何らかの形で OleVariant に配置されている可能性がありますか?

于 2009-01-27T16:10:06.323 に答える