4

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?

Kromster
  • 7,181
  • 7
  • 63
  • 111

2 Answers2

4

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;
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
0

The VarUtils unit has the SafeArrayCreate function, remember to call SafeArrayDestroy (preferably in a try/finally section)!

Stijn Sanders
  • 35,982
  • 11
  • 45
  • 67
  • 1
    The original code already calls that. How does that answer the question? – Rob Kennedy Aug 21 '12 at 12:40
  • The original code used `VarArrayCreate()` instead, which wraps the SafeArray inside a `Variant`. `SafeArrayCreate()`, on the other hand, returns the SafeArray pointer directly. – Remy Lebeau Aug 21 '12 at 18:12