Search code examples
delphicomsafearray

Error on call COM with PSafeArray in delphi7


I have a procedure that I need to call using COM, which is declared like this in C#:

public string ali(int[] num)
{
    string r;
    r ="";
    foreach (int a in num)
    {
        r = r + Convert.ToString(a) + ";";   
    }
    return r;
}

The Delphi declaration in the imported TypeLibrary is:

function TSqr.ali(num: PSafeArray): WideString;
begin
  Result := DefaultInterface.ali(num);
end;

I have this code to convert integer Array into a PSafeArray:

Function ArrayToSafeArray2 (DataArray: array of integer):PSafeArray;
var
  SafeArray: PSafeArray;
  InDataLength,i: Integer;
  vaInMatrix: Variant;
begin
  InDataLength := Length(DataArray);
  vaInMatrix := VarArrayCreate([Low(DataArray), High(DataArray)], varInteger);
  for i:= Low(DataArray) to High(DataArray) do
  begin
    vaInMatrix[I] :=  DataArray[I];
  end;
  SafeArray := PSafeArray(TVarData(vaInMatrix).VArray);
  Result := SafeArray;
  VarClear(vaInMatrix);
  SafeArrayDestroy(SafeArray);
end;

and this code to call my COM function

var
  a:array of integer;
  Answer:String;
begin
  SetLength(a,3);

  a[0] := 1;
  a[1] := 2;
  a[2] := 2;

  Answer := Sqr1.ali(ArrayToSafeArray2(a));
  ShowMessage(Answer);
end;

but error ocure:

" EOLeExeption with message 'SafeArray of rank 0 has been passed to method expecting an array of rank 1' ..."

what i should be do?


Solution

  • Your conversion routine is destroying the SafeArray before the caller can use it. Unlike Delphi arrays, COM arrays are not reference counted. Don't destroy the SafeArray until after you have passed it to the COM procedure, eg:

    function ArrayToSafeArray2 (DataArray: array of integer): Variant;
    var
      i: Integer;
    begin
      Result := VarArrayCreate([Low(DataArray), High(DataArray)], varInteger);
      for i:= Low(DataArray) to High(DataArray) do
      begin
        Result[I] := DataArray[I];
      end;
    end;
    

    .

    var
      a:array of integer;
      v: Variant;
      Answer:String;
    begin
      SetLength(a,3);
    
      a[0] := 1;
      a[1] := 2;
      a[2] := 2;
    
      v := ArrayToSafeArray2(a);
    
      Answer := Sqr1.ali(TVarData(v).VArray);
      ShowMessage(Answer);
    end;