Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to display values from a VARIANT with a SAFEARRAY of BSTRs

I am working on a COM Object library with function that returns a VARIANT with a SAFEARRAY of BSTRs. How can I display the values from this VARIANT instance and save it inside a TStringList? I tried searching the net with no clear answer.

I tried the following with no success:

Variant V;
String mystr;

VarClear(V);
TVarData(V).VType = varOleStr;
V = ComFunction->GetValues();  //<<<<----- V is empty
mystr = (wchar_t *)(TVarData(V).VString);
Memo1->Lines->Add(mystr);
VarClear(V);
like image 427
Heb Avatar asked Dec 19 '11 07:12

Heb


2 Answers

You can use TWideStringDynArray and let Delphi do the conversion:

procedure LoadStringsFromVariant(const Values: TWideStringDynArray; Strings: TStrings);
var
  I: Integer;
begin
  Strings.BeginUpdate;
  try
    for I := Low(Values) to High(Values) do
      Strings.Add(Values[I]);
  finally
    Strings.EndUpdate;
  end;
end;

When you call this with your Variant safearray of BSTRs it will be converted to TWideStringDynArray automatically. An incompatible Variant will cause the runtime error EVariantInvalidArgError.

To check if a Variant holds a safe array of BSTR you can do this:

IsOK := VarIsArray(V) and (VarArrayDimCount(V) = 1) and (VarType(V) and varTypeMask = varOleStr);
like image 183
Ondrej Kelle Avatar answered Oct 14 '22 03:10

Ondrej Kelle


uses ActiveX;

var
  VSafeArray: PSafeArray;
  LBound, UBound, I: LongInt;
  W: WideString;
begin
  VSafeArray := ComFunction.GetValues();
  SafeArrayGetLBound(VSafeArray, 1, LBound);
  SafeArrayGetUBound(VSafeArray, 1, UBound);
  for I := LBound to UBound do
  begin
    SafeArrayGetElement(VSafeArray, I, W);
    Memo1.Lines.Add(W);
  end;
  SafeArrayDestroy(VSafeArray); // cleanup PSafeArray

if you are creating ComFunction via late binding (CreateOleObject) you should use:

var
  v: Variant;
v := ComFunction.GetValues;
for i := VarArrayLowBound(v, 1) to VarArrayHighBound(v, 1) do
begin 
  W := VarArrayGet(v, [i]);
  Memo1.Lines.Add (W);
end;
like image 36
kobik Avatar answered Oct 14 '22 04:10

kobik