Pergunta

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?

Foi útil?

Solução

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;

Outras dicas

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

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top