Ошибка недопустимого варианта операции при попытке доступа к OleVariant в Delphi - Работает в C # - PullRequest
0 голосов
/ 27 января 2009

Я пытаюсь получить доступ к OleVariant в обратном вызове, поступающем из библиотеки ActiveX.

Вот как определяется обработчик события в TLB:

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

Вот определение structVTIQSnap в TLB:

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;

Как получить доступ к structQSnap и его свойствам в Delphi?

В C # эта функция отлично работает для обработчика событий:

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

Есть идеи?

Ответы [ 4 ]

8 голосов
/ 27 января 2009

Я думаю, что мастер импорта ActiveX в Delphi не знает, как правильно обрабатывать тип structVTIQSnap (который выглядит как запись), и просто использует OleVariant по умолчанию. Существует ли объявление типа с именем structVTIQSnap или подобное в сгенерированном файле ..._ TLB.pas? Попробуйте использовать это вместо OleVariant, например

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

Тип, вероятно, будет объявлен как "упакованная запись".

1 голос
/ 27 января 2009

Вы можете попытаться ввести 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;

Что я не понимаю, так это следующее: я взял из ref в коде C #, что структура должна быть распределена дважды: один раз из библиотеки в обратный вызов, второй обратно в библиотеку , Это будет означать, что флаг varByRef ($ 4000) должен быть установлен в VType, но значение, которое вы дали в своем комментарии (3484), слишком мало?

0 голосов
/ 27 января 2009

Я не уверен, почему вы рассматриваете "structVTIQSnap" как "OleVariant". Мне кажется странным перевод. Может ли быть так, что он был помещен в OleVariant в какой-либо форме, в виде массива или аналогичного?

0 голосов
/ 27 января 2009

попробуй посмотреть, что возвращает в TVarData (structQSnap) .VType?

может быть, это будет работать:

 var
   symbol: WideString;
   rec: structVTIQSnap;
 begin
    rec := structVTIQSnap(structQSnap);
    symbol := rec.bstrSymbol; 
 end;
...