The mysteries of PSafeArray

I use Delphi 7 for all my Windows projects, nice simple clean, easy maintainable AND Pascal. However if you find yourself lost in COM and automation, all of a sudden strange variable types appear like varArray, OleVariants, U/L bounds and PSafeArray’s and it´s getting worse: their initialization/finalization do not use Object.Free, Dispose() and the like anymore! As far I can understand its all about marshalling; the process of converting variables to COM variables and back..

PSafeArray is defined in ActiveX.pas:

  PSafeArray = ^TSafeArray;
  tagSAFEARRAY = record
    cDims: Word;
    fFeatures: Word;
    cbElements: Longint;
    cLocks: Longint;
    pvData: Pointer;
    rgsabound: array[0..0] of TSafeArrayBound;
  TSafeArray = tagSAFEARRAY;
  SAFEARRAY = TSafeArray;

Instantiate and free PSafeArray directly:

  Bounds: array[0..0] of TSafeArrayBound;
  SafeArray: PSafeArray;
  Bounds[0].lLbound   := 0;
  Bounds[0].cElements := 100;
  SafeArray := SafeArrayCreate(VT_I1, 1, Bounds);

Typecast and multidimensional example:

  Data: Variant;
  SafeArray: PSafeArray;
  Data      := VarArrayCreate([0, 1, 0, 2], VT_VARIANT);
  Data[0,0] := 1;
  Data[0,1] := 'some text';
  Data[0,2] := Now();
  Data[1,0] := 2;
  Data[1,1] := 'more text';
  Data[1,2] := Now();
  SafeArray := PSafeArray(TVarData(Data).VArray);

To sum it up I´ve created an example inwhich a good ole pascal array is converted into an varArray which in turn is converted to an PSafeArray and back again to plain pascal:

procedure SMA(InData: TArrayOfDouble; Period: Integer; var OutData: TArrayOfDouble);
  psaInMatrix, psaOutMatrix: PSafeArray;
  vaInMatrix: Variant;
  LBound, HBound : Integer;

  I: Integer;
  InDataLength: Integer;
  D: Double;
  //create varArray
  InDataLength := Length(InData);
  vaInMatrix := VarArrayCreate([0, InDataLength-1], varDouble);

  //copy data into varArray
  for I := 0 to InDataLength-1 do
    vaInMatrix[I] := InData[I];

  //typecast magic
  psaInMatrix := PSafeArray(TVarData(vaInMatrix).VArray);

  //COM call with a PSafeArray as return value
  psaOutMatrix := COM.SimpleMovingAverage(psaInMatrix, Period);

  //enum PSafeArray
  SafeArrayGetLBound(psaOutMatrix, 1, LBound);
  SafeArrayGetUBound(psaOutMatrix, 1, HBound);

    //copy data
  SetLength(OutData, HBound+1);
  for I := LBound to HBound do
    SafeArrayGetElement(psaOutMatrix, I, D);
    OutData[I] := D;

  //cleanup varArray

  //cleanup PSafeArray

This function can be called in the following way:

  TArrayOfDouble = array of Double;
  InData, OutData: TArrayOfDouble;
  SetLength(InData, 9);
  InData[0] := 2.48;
  InData[1] := 2.54;
  InData[2] := 2.56;
  InData[3] := 2.48;
  InData[4] := 2.54;
  InData[5] := 2.56;
  InData[6] := 2.48;
  InData[7] := 2.54;
  InData[8] := 2.56;

  SMA(InData, 3, OutData);

Last but not least, to enumerate an varArray use something like this:

for I := VarArrayLowBound(vaInMatrix, 1) to VarArrayHighBound(vaInMatrix, 1) do
  Memo1.Lines.Add(FloatToStr( vaInMatrix[I] ));

FloatToStr is needed here because the varArray was created with varDouble.

Further readings:

July 20th, 2008 - Posted in delphi | |

6 Responses to ' The mysteries of PSafeArray '

Subscribe to comments with RSS or TrackBack to ' The mysteries of PSafeArray '.

  1. evilripper said,

    on November 12th, 2009 at 8:43 pm

    Thank you a lot, you save my brain today!! This pSafeArray maked me crazy!

    Why in delphi there is a unit varUtils where there are the same procedures that there are in ActiveX.pas????? oh my god :-D

  2. on August 6th, 2011 at 8:47 am

    […] a look at this article, which explains how to get data in and out of a PSafeArray in […]

  3. cheap_cialis said,

    on October 7th, 2016 at 11:27 am

    Que es mejor levitra o cheap cialis - Best web drugstore to come to for effective drugs - zukunftspiloten.

  4. generic said,

    on December 6th, 2016 at 9:51 am

    Generic buying generic cialis Paypal Payment, Top Offering, Best Prices For All Customers!

  5. on January 25th, 2017 at 1:44 pm

    My breath as I entertainment is provided for do not take generic cialis for sale station agent for help.

  6. cialis_sale said,

    on January 25th, 2017 at 4:22 pm

    Hairdryer cialis sale prices online Eyes buying, for buy cheap cialis palyinfocus.

Leave a reply